# Hive SQL 语法参考 ## 数据类型 | 类型 | 说明 | 示例 | |------|------|------| | 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) | | BOOLEAN | 布尔 | active BOOLEAN | | STRING | 变长字符串 | name STRING | | VARCHAR(n) | 变长字符串(限长) | code VARCHAR(50) | | CHAR(n) | 定长字符串 | flag CHAR(1) | | DATE | 日期 | birth_date DATE | | TIMESTAMP | 时间戳(纳秒精度) | created_at TIMESTAMP | | BINARY | 二进制 | data BINARY | | ARRAY\ | 数组 | tags ARRAY\ | | MAP\ | 映射 | props MAP\ | | STRUCT\ | 结构体 | user STRUCT\ | | UNIONTYPE\ | 联合类型 | value UNIONTYPE\ | --- ## 时间函数 ```sql -- 当前时间 current_date() -- 当前日期 current_timestamp() -- 当前时间戳 unix_timestamp() -- 当前 Unix 时间戳(秒) -- 格式转换 date_format(date_col, 'yyyy-MM-dd') -- 日期格式化 date_format(timestamp_col, 'yyyy-MM-dd HH:mm:ss') -- 时间格式化 to_date(string_col) -- 字符串转日期 to_date(string_col, 'yyyy-MM-dd') -- 字符串转日期(带格式) from_unixtime(timestamp) -- Unix 时间戳转字符串 from_unixtime(timestamp, 'yyyy-MM-dd') -- 带格式转换 -- 日期计算 date_add(date_col, 7) -- 加7天 date_sub(date_col, 7) -- 减7天 add_months(date_col, 3) -- 加3个月 datediff(end_date, start_date) -- 日期差(天数) months_between(date1, date2) -- 月份差 -- 日期提取 year(date_col) -- 年 month(date_col) -- 月 day(date_col) -- 日 dayofmonth(date_col) -- 月中第几天 dayofweek(date_col) -- 周几 (1=周日, 7=周六) hour(timestamp_col) -- 时 minute(timestamp_col) -- 分 second(timestamp_col) -- 秒 quarter(date_col) -- 季度 (1-4) weekofyear(date_col) -- 年中第几周 last_day(date_col) -- 月末日期 trunc(date_col, 'MM') -- 月初日期 trunc(date_col, 'YY') -- 年初日期 -- Unix 时间戳 unix_timestamp(date_col) -- 转 Unix 时间戳 unix_timestamp(string_col, 'yyyy-MM-dd') -- 指定格式转换 from_unixtime(timestamp) -- Unix 时间戳转字符串 ``` --- ## 字符串函数 ```sql -- 常用函数 concat(str1, str2, ...) -- 字符串拼接 concat_ws('-', str1, str2, ...) -- 用分隔符拼接 lower(str) -- 转小写 upper(str) -- 转大写 trim(str) -- 去两端空格 ltrim(str) -- 去左空格 rtrim(str) -- 去右空格 length(str) -- 字符串长度 substring(str, pos, len) -- 截取字符串(pos从1开始) substr(str, pos, len) -- 同 substring 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(str, delimiter) -- 分割成数组 -- 其他 initcap(str) -- 首字母大写 lpad(str, len, pad) -- 左填充 rpad(str, len, pad) -- 右填充 hex(col) -- 转16进制 unhex(str) -- 16进制转字符串 ``` --- ## 聚合函数 ```sql -- 基础聚合 COUNT(*) -- 计数(含NULL行) COUNT(col) -- 计数(不含NULL) COUNT(DISTINCT col) -- 去重计数 SUM(col) -- 求和 AVG(col) -- 平均值 MIN(col) -- 最小值 MAX(col) -- 最大值 -- 集合聚合 collect_list(col) -- 返回数组(不去重) collect_set(col) -- 返回数组(去重) -- 统计函数 variance(col) -- 方差 var_pop(col) -- 总体方差 var_samp(col) -- 样本方差 stddev(col) -- 标准差 stddev_pop(col) -- 总体标准差 stddev_samp(col) -- 样本标准差 -- 近似函数 approx_count_distinct(col) -- 近似去重计数(大数据量优化) -- 其他 first(col) -- 第一个值 last(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) -- NVL(空值替换) NVL(col, default_value) ``` --- ## 复杂类型操作 ```sql -- ARRAY 操作 array(val1, val2, ...) -- 创建数组 array_contains(arr, val) -- 判断是否包含 element_at(arr, idx) -- 取元素(idx从1开始) arr[idx] -- 取元素(idx从0开始) size(arr) -- 数组长度 array_join(arr, delimiter) -- 数组转字符串 sort_array(arr) -- 排序 array_distinct(arr) -- 去重 -- 展开(LATERAL VIEW + explode) -- 展开数组 SELECT id, tag FROM table LATERAL VIEW explode(tags) t AS tag; -- 展开数组带索引 SELECT id, pos, tag FROM table LATERAL VIEW posexplode(tags) t AS pos, tag; -- 展开 Map SELECT id, map_key, map_value FROM table LATERAL VIEW explode(props) m AS map_key, map_value; -- MAP 操作 map(key1, val1, key2, val2) -- 创建 Map str_to_map(str, delim1, delim2) -- 字符串转 Map map_contains(map, key) -- 判断是否包含key map_keys(map) -- 所有 key(返回数组) map_values(map) -- 所有 value(返回数组) size(map) -- Map大小 -- STRUCT 操作 named_struct('name1', val1, 'name2', val2) -- 创建结构体 struct_col.field_name -- 访问结构体字段 ``` --- ## 分区表操作 ```sql -- 创建分区表 CREATE TABLE target_table ( id BIGINT, name STRING, amount DECIMAL(18,2) ) PARTITIONED BY (day_id STRING) STORED AS ORC; -- 静态分区写入 INSERT OVERWRITE TABLE target_table PARTITION (day_id = '${day_id}') SELECT id, name, amount FROM source_table; -- 动态分区写入 SET hive.exec.dynamic.partition = true; SET hive.exec.dynamic.partition.mode = nonstrict; INSERT OVERWRITE TABLE target_table PARTITION (day_id) SELECT id, name, amount, day_id FROM source_table; -- 分区管理 SHOW PARTITIONS target_table; ALTER TABLE target_table ADD IF NOT EXISTS PARTITION (day_id = '2026-05-10'); ALTER TABLE target_table DROP IF EXISTS PARTITION (day_id = '2026-01-01'); -- MSCK REPAIR(恢复分区元数据) MSCK REPAIR TABLE target_table; ``` --- ## 与 Spark SQL 的主要差异 | 特性 | Spark SQL | Hive | 说明 | |------|-----------|------|------| | **LEFT SEMI JOIN** | ✅ 独立语法 | ✅ 支持(语义相同) | Hive 也可用 IN 子查询替代 | | **LEFT ANTI JOIN** | ✅ 独立语法 | ✅ 支持(语义相同) | Hive 也可用 NOT IN 替代 | | **CTE (WITH)** | ✅ 支持 | ✅ Hive 0.13+ 支持 | 都支持但 Hive 中推荐物化临时表 | | **INSERT OVERWRITE** | ✅ 支持 | ✅ 支持 | 写法一致 | | **MERGE INTO** | ✅ 支持 | ❌ 不支持 | Hive 不支持 | | **UPDATE/DELETE** | ❌ 不支持 | 仅 ACID 表支持 | 普通 Hive 表不支持 | | **collect_list/set** | ✅ 支持 | ✅ 支持 | 完全一致 | | **LATERAL VIEW** | ✅ 支持 | ✅ 支持(Hive 原生) | Hive 首创的语法 | | **分桶 JOIN** | 可优化 | 可优化(SMB JOIN) | Hive 分桶优化更成熟 | | **日期格式** | `yyyy-MM-dd` | `yyyy-MM-dd` | 格式一致 | | **临时表** | CREATE TEMP TABLE | CREATE TEMPORARY TABLE | 关键字略有不同 | | **存储格式** | PARQUET/ORC | ORC/PARQUET/TEXTFILE | Hive 支持 TEXTFILE | | **分区发现** | 自动 | 需 MSCK REPAIR 或 ALTER | Hive 需手动恢复 | | **复杂类型** | 完整支持 | 完整支持 | 基本一致 | | **窗口函数** | ✅ 完整支持 | ✅ 完整支持 | 语法一致 | --- ## 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_{业务简称}_{步骤序号}` ### Hive 特有规则 1. 使用 `INSERT OVERWRITE TABLE ... PARTITION (...)` 写入目标表 2. 动态分区需先 `SET hive.exec.dynamic.partition = true;` 3. 分区列不能出现在表定义的列中(Hive 特有约束) 4. 支持 `collect_list` / `collect_set` 聚合 5. 支持 `LATERAL VIEW explode()` 展开数组 6. 日期函数:`date_format()`, `to_date()`, `date_add()`, `add_months()`(和 Spark 一致) 7. 时间范围筛选: ```sql -- 日账期过滤 WHERE day_id = '${day_id}' -- 最近N个月(月份格式 yyyyMM) WHERE month_id >= date_format(add_months(to_date('${month_id}', 'yyyyMM'), -N), 'yyyyMM') AND month_id < '${month_id}' ``` ### SQL 脚本结构 ```sql -- ===================================================================== -- @SqlName: hive-D-SQL-{表名} -- @Engine: hive -- ...(头注释) -- ===================================================================== -- 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 ...; -- 最后一步:写入目标表 INSERT OVERWRITE TABLE ${db_eda_env}.target_table PARTITION (day_id = '${day_id}') SELECT ...; ```