# Kudu (via Impala) SQL 语法参考 > **重要**:Kudu 本身没有 SQL 引擎,通过 Impala 访问。本文档是 Impala SQL 操作 Kudu 表的语法参考。 ## 数据类型 | 类型 | 说明 | 示例 | |------|------|------| | BOOLEAN | 布尔 | active BOOLEAN | | TINYINT | 1字节整数 | level TINYINT | | SMALLINT | 2字节整数 | age SMALLINT | | INT | 4字节整数 | count INT | | BIGINT | 8字节整数 | id BIGINT | | FLOAT | 4字节浮点 | score FLOAT | | DOUBLE | 8字节浮点 | price DOUBLE | | DECIMAL(p,s) | 定点数 | amount DECIMAL(18,2) | | STRING | 变长字符串 | name STRING | | VARCHAR(n) | 变长字符串(限长) | code VARCHAR(50) | | CHAR(n) | 定长字符串 | flag CHAR(1) | | TIMESTAMP | 时间戳(微秒精度) | created_at TIMESTAMP | | DATE | 日期 | birth_date DATE | | BINARY | 二进制 | data BINARY | **注意**:Kudu 不支持 ARRAY、MAP、STRUCT 等复杂类型。 --- ## 时间函数 ```sql -- 当前时间 NOW() -- 当前日期时间 CURRENT_TIMESTAMP() -- 当前时间戳 UNIX_TIMESTAMP() -- 当前 Unix 时间戳(秒) TO_DATE(NOW()) -- 当前日期 -- 格式转换 FROM_UNIXTIME(timestamp, 'yyyy-MM-dd') -- Unix 时间戳转格式化字符串 FROM_UNIXTIME(timestamp, 'yyyy-MM-dd HH:mm:ss') CAST(string_col AS TIMESTAMP) -- 字符串转时间戳 CAST(timestamp_col AS STRING) -- 时间戳转字符串 -- 日期计算 DAYS_ADD(date_col, 7) -- 加7天 DAYS_SUB(date_col, 7) -- 减7天 ADD_MONTHS(date_col, 3) -- 加3个月(Impala 6.0+) DATE_ADD(date_col, INTERVAL 7 DAY) -- 加7天(标准语法) DATEDIFF(end_date, start_date) -- 日期差(天数) MONTHS_BETWEEN(date1, date2) -- 月份差 -- 日期提取 YEAR(date_col) -- 年 MONTH(date_col) -- 月 DAY(date_col) -- 日 DAYOFWEEK(date_col) -- 周几 (1=周日) DAYOFYEAR(date_col) -- 年中第几天 HOUR(timestamp_col) -- 时 MINUTE(timestamp_col) -- 分 SECOND(timestamp_col) -- 秒 QUARTER(date_col) -- 季度 (1-4) WEEKOFYEAR(date_col) -- 年中第几周 -- Impala 日期格式符 -- yyyy: 4位年, MM: 2位月, dd: 2位日 -- HH: 24小时制, mm: 分钟, ss: 秒 ``` --- ## 字符串函数 ```sql -- 常用函数 CONCAT(str1, str2) -- 字符串拼接(仅2个参数) CONCAT_WS('-', str1, str2, ...) -- 用分隔符拼接 LOWER(str) -- 转小写 UPPER(str) -- 转大写 TRIM(str) -- 去两端空格 LTRIM(str) -- 去左空格 RTRIM(str) -- 去右空格 LENGTH(str) -- 字符串长度 SUBSTR(str, pos, len) -- 截取字符串(pos从1开始) SUBSTRING(str, pos, len) -- 同上 LEFT(str, len) -- 取左边len个字符 RIGHT(str, len) -- 取右边len个字符 REVERSE(str) -- 反转字符串 REPEAT(str, n) -- 重复n次 SPACE(n) -- 生成n个空格 -- 查找与替换 INSTR(str, substr) -- 查找子串位置 LOCATE(substr, str, pos) -- 从pos位置查找 REPLACE(str, old, new) -- 替换 REGEXP_EXTRACT(str, pattern, idx) -- 正则提取 REGEXP_REPLACE(str, pattern, replacement) -- 正则替换 -- 分割 SPLIT_PART(str, delimiter, idx) -- 取分割后第idx部分 -- 其他 INITCAP(str) -- 首字母大写 LPAD(str, len, pad) -- 左填充 RPAD(str, len, pad) -- 右填充 HEX(col) -- 转16进制 UNHEX(str) -- 16进制转字符串 ``` **注意**:Impala 的 `CONCAT` 只接受 2 个参数,多参数拼接用 `CONCAT_WS`。 --- ## 聚合函数 ```sql -- 基础聚合 COUNT(*) -- 计数(含NULL行) COUNT(col) -- 计数(不含NULL) COUNT(DISTINCT col) -- 去重计数 SUM(col) -- 求和 AVG(col) -- 平均值 MIN(col) -- 最小值 MAX(col) -- 最大值 -- 集合聚合 GROUP_CONCAT(col SEPARATOR ',') -- 字符串聚合 -- 统计函数 VARIANCE(col) -- 方差 VAR_POP(col) -- 总体方差 VAR_SAMP(col) -- 样本方差 STDDEV(col) -- 标准差 STDDEV_POP(col) -- 总体标准差 STDDEV_SAMP(col) -- 样本标准差 -- 近似函数 NDV(col) -- 近似去重计数(Impala 特有,比 COUNT(DISTINCT) 快) APPROX_COUNT_DISTINCT(col) -- 近似去重计数 -- 其他 FIRST_VALUE(col) -- 窗口内第一个值 LAST_VALUE(col) -- 窗口内最后一个值 ``` --- ## 条件表达式 ```sql -- CASE WHEN CASE WHEN condition1 THEN result1 WHEN condition2 THEN result2 ELSE default_result END -- CASE 字段匹配 CASE field WHEN value1 THEN result1 WHEN value2 THEN result2 ELSE default_result END -- COALESCE(取第一个非空值) COALESCE(col1, col2, default_value) -- NULLIF(相等返回NULL) NULLIF(col1, col2) -- IF(简单条件) IF(condition, true_value, false_value) -- ISNULL / ISNOTNULL ISNULL(col) -- 判断是否为NULL ISNOTNULL(col) -- 判断是否不为NULL -- NVL(空值替换) NVL(col, default_value) ``` --- ## Kudu 特有操作 ### INSERT INTO ```sql -- 追加写入 INSERT INTO kudu_table VALUES (1, 'test', 100.00); INSERT INTO kudu_table SELECT * FROM other_table WHERE ...; ``` ### UPSERT INTO(Kudu 核心能力) ```sql -- 主键存在则更新,不存在则插入 UPSERT INTO kudu_table VALUES (1, 'test', 100.00); UPSERT INTO kudu_table SELECT * FROM staging_table WHERE ...; ``` ### UPDATE ```sql -- 更新数据(主键列不可更新) UPDATE kudu_table SET status = 'active' WHERE id = 1; UPDATE kudu_table SET amount = amount * 1.1 WHERE date < '2026-01-01'; ``` ### DELETE ```sql -- 删除数据 DELETE FROM kudu_table WHERE id = 1; DELETE FROM kudu_table WHERE date < '2026-01-01'; ``` ### ALTER TABLE(Kudu 特有) ```sql -- 添加列 ALTER TABLE kudu_table ADD COLUMNS (new_col STRING COMMENT '新列'); -- 删除列 ALTER TABLE kudu_table DROP COLUMN old_col; -- 修改列类型 ALTER TABLE kudu_table CHANGE old_name new_name STRING; -- 添加范围分区 ALTER TABLE kudu_table ADD RANGE PARTITION '2026-06-01' <= VALUES < '2026-07-01'; -- 删除范围分区 ALTER TABLE kudu_table DROP RANGE PARTITION '2026-01-01' <= VALUES < '2026-02-01'; ``` --- ## 分区操作 ```sql -- Hash 分区(建表时指定) PARTITION BY HASH(id) PARTITIONS 8 -- Range 分区(建表时指定) PARTITION BY RANGE(stat_date) ( PARTITION '2026-01-01' <= VALUES < '2026-02-01', PARTITION '2026-02-01' <= VALUES < '2026-03-01' ) -- Hash + Range 组合 PARTITION BY HASH(id) PARTITIONS 4, RANGE(stat_date) (...) ``` --- ## 与 Spark SQL / Hive 的主要差异 | 特性 | Spark SQL | Hive | Kudu (Impala) | 说明 | |------|-----------|------|--------------|------| | **INSERT OVERWRITE** | ✅ | ✅ | ❌ | Kudu 不支持,用 DELETE + INSERT 替代 | | **UPSERT** | ❌ | ❌ | ✅ | Kudu 独有核心能力 | | **UPDATE** | ❌ | 仅ACID表 | ✅ | Kudu 原生支持 | | **DELETE** | ❌ | 仅ACID表 | ✅ | Kudu 原生支持 | | **主键约束** | ❌ 无约束 | ❌ 无约束 | ✅ 强制主键 | Kudu 表必须有主键 | | **复杂类型** | ✅ ARRAY/MAP/STRUCT | ✅ 完整支持 | ❌ 不支持 | Kudu 限制 | | **CONCAT 多参数** | ✅ 任意个数 | ✅ 任意个数 | ❌ 仅2个参数 | Impala 用 CONCAT_WS | | **近似去重** | `approx_count_distinct` | `approx_count_distinct` | `NDV` | Impala 特有函数名 | | **临时表链式处理** | ✅ 推荐 | ✅ 推荐 | ❌ 不需要 | Kudu 用 UPSERT 单步 | | **CTE (WITH)** | ✅ 支持 | ✅ 支持 | ✅ 支持 | 都支持 | | **MERGE INTO** | ✅ 支持 | ❌ | ❌ | 用 UPSERT 替代 | | **分区类型** | 目录分区 | 目录分区 | Hash/Range 内置 | Kudu 分区机制不同 | | **分桶** | 可选 | 可选 | Hash 分区替代 | 概念类似但实现不同 | | **日期格式** | `yyyy-MM-dd` | `yyyy-MM-dd` | `yyyy-MM-dd` | 格式一致 | | **collect_list/set** | ✅ | ✅ | ❌ | Impala 用 GROUP_CONCAT | | **ALTER ADD COLUMN** | ✅ | ✅ | ✅ | Kudu 支持在线加列 | | **ALTER DROP COLUMN** | 部分支持 | ✅ | ✅ | Kudu 支持在线删列 | --- ## SQL 生成规则 ### 通用规则(所有引擎统一) 1. **禁止使用 CTE (WITH 子句)**,每个主要逻辑步骤必须物化为临时表 2. **先 DROP 再 CREATE**:`DROP TABLE IF EXISTS ...; CREATE TABLE ... AS SELECT ...;` 3. **禁止 `SELECT *`**,必须明确列出所有字段 4. 多表查询时所有表必须使用简短别名 5. 每个步骤前添加注释说明 6. **谓词下推**:过滤条件前置,JOIN 时在 WHERE 中一并添加过滤 7. 临时表命名:`${db_tmp_env}.tmp_{业务简称}_{步骤序号}` ### Kudu 特有规则 1. **Kudu 表不支持 `INSERT OVERWRITE`**,用 `DELETE + INSERT` 或 `UPSERT` 替代 2. **最后一步优先使用 `UPSERT INTO`**(Kudu 核心优势:主键存在则更新,不存在则插入) 3. 需要全量刷新时:先 `DELETE FROM` 再 `INSERT INTO` 4. 支持 `UPDATE` 和 `DELETE`(Kudu 表独有) 5. Kudu 表必须有 `PRIMARY KEY`,主键列不能为 NULL 6. `CONCAT` 只接受 2 个参数,多参数用 `CONCAT_WS` 7. 不支持 `collect_list` / `collect_set`,用 `GROUP_CONCAT` 替代 8. 近似去重用 `NDV()` 函数 9. 时间范围筛选: ```sql -- 日账期过滤 WHERE stat_date = '${day_id}' -- 日期范围 WHERE stat_date >= DAYS_SUB(TO_DATE('${day_id}'), 30) AND stat_date < '${day_id}' ``` ### SQL 脚本结构 ```sql -- ===================================================================== -- @SqlName: kudu-D-SQL-{表名} -- @Engine: kudu -- ...(头注释) -- ===================================================================== -- Step01: {步骤描述} DROP TABLE IF EXISTS ${db_tmp_env}.tmp_xxx_01; CREATE TABLE ${db_tmp_env}.tmp_xxx_01 AS SELECT ...; -- Step02: {步骤描述} DROP TABLE IF EXISTS ${db_tmp_env}.tmp_xxx_02; CREATE TABLE ${db_tmp_env}.tmp_xxx_02 AS SELECT ...; -- 最后一步:UPSERT 写入 Kudu 目标表 UPSERT INTO ${db_eda_env}.target_table SELECT ...; ```