Add one-skill
This commit is contained in:
@@ -0,0 +1,211 @@
|
||||
-- =====================================================================
|
||||
-- @Name: HIVE-D-SQL-{表名}-CREATE
|
||||
-- @Version: 1.0
|
||||
-- @Desc: Hive 建表模板(内部表/外部表/分区/分桶)
|
||||
-- @TargetDatabase: Hive
|
||||
-- =====================================================================
|
||||
|
||||
-- ============================================================================
|
||||
-- 场景1:内部表(Managed Table)
|
||||
-- ============================================================================
|
||||
-- 适用:Hive 管理数据和元数据,DROP TABLE 时数据一并删除
|
||||
|
||||
CREATE TABLE IF NOT EXISTS db_name.managed_table (
|
||||
id BIGINT COMMENT '主键ID',
|
||||
name STRING COMMENT '名称',
|
||||
category STRING COMMENT '类别',
|
||||
amount DECIMAL(18,2) COMMENT '金额',
|
||||
status STRING COMMENT '状态',
|
||||
created_at TIMESTAMP COMMENT '创建时间',
|
||||
updated_at TIMESTAMP COMMENT '更新时间',
|
||||
etl_time TIMESTAMP COMMENT '数据加工时间',
|
||||
etl_remark STRING COMMENT '备注信息'
|
||||
)
|
||||
COMMENT '内部表示例'
|
||||
STORED AS ORC; -- 推荐存储格式
|
||||
|
||||
-- ============================================================================
|
||||
-- 场景2:外部表(External Table)
|
||||
-- ============================================================================
|
||||
-- 适用:数据由外部系统管理,DROP TABLE 只删元数据不删数据
|
||||
|
||||
CREATE EXTERNAL TABLE IF NOT EXISTS db_name.external_table (
|
||||
id BIGINT COMMENT '主键ID',
|
||||
user_id STRING COMMENT '用户ID',
|
||||
action STRING COMMENT '操作类型',
|
||||
page_url STRING COMMENT '页面URL',
|
||||
ip_address STRING COMMENT 'IP地址',
|
||||
event_time TIMESTAMP COMMENT '事件时间'
|
||||
)
|
||||
COMMENT '日志外部表'
|
||||
ROW FORMAT DELIMITED
|
||||
FIELDS TERMINATED BY '\t'
|
||||
LINES TERMINATED BY '\n'
|
||||
STORED AS TEXTFILE
|
||||
LOCATION '/data/external/logs/';
|
||||
|
||||
-- ============================================================================
|
||||
-- 场景3:分区表(单分区)
|
||||
-- ============================================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS db_name.partitioned_table (
|
||||
id BIGINT COMMENT '主键ID',
|
||||
user_id STRING COMMENT '用户ID',
|
||||
user_name STRING COMMENT '用户姓名',
|
||||
order_count BIGINT COMMENT '订单数',
|
||||
total_amount DECIMAL(18,2) COMMENT '总金额',
|
||||
department STRING COMMENT '部门',
|
||||
region STRING COMMENT '地区',
|
||||
etl_time TIMESTAMP COMMENT '数据加工时间'
|
||||
)
|
||||
COMMENT '按日分区的统计表'
|
||||
PARTITIONED BY (day_id STRING COMMENT '统计日期,格式yyyy-MM-dd')
|
||||
STORED AS ORC;
|
||||
|
||||
-- ============================================================================
|
||||
-- 场景4:多分区字段
|
||||
-- ============================================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS db_name.multi_partition_table (
|
||||
id BIGINT COMMENT '主键ID',
|
||||
name STRING COMMENT '名称',
|
||||
amount DECIMAL(18,2) COMMENT '金额',
|
||||
etl_time TIMESTAMP COMMENT '数据加工时间'
|
||||
)
|
||||
COMMENT '多分区字段示例表'
|
||||
PARTITIONED BY (
|
||||
year_id STRING COMMENT '年份',
|
||||
month_id STRING COMMENT '月份'
|
||||
)
|
||||
STORED AS ORC;
|
||||
|
||||
-- ============================================================================
|
||||
-- 场景5:分桶表
|
||||
-- ============================================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS db_name.bucketed_table (
|
||||
id BIGINT COMMENT '主键ID',
|
||||
user_id BIGINT COMMENT '用户ID',
|
||||
user_name STRING COMMENT '用户姓名',
|
||||
amount DECIMAL(18,2) COMMENT '金额'
|
||||
)
|
||||
COMMENT '分桶表示例'
|
||||
PARTITIONED BY (day_id STRING)
|
||||
CLUSTERED BY (user_id) -- 分桶列
|
||||
SORTED BY (amount DESC) -- 桶内排序
|
||||
INTO 16 BUCKETS -- 桶数量
|
||||
STORED AS ORC;
|
||||
|
||||
-- ============================================================================
|
||||
-- 场景6:ORC 格式 + 表属性
|
||||
-- ============================================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS db_name.orc_table (
|
||||
id BIGINT COMMENT '主键ID',
|
||||
name STRING COMMENT '名称',
|
||||
amount DECIMAL(18,2) COMMENT '金额',
|
||||
etl_time TIMESTAMP COMMENT '数据加工时间'
|
||||
)
|
||||
COMMENT 'ORC格式带属性配置'
|
||||
PARTITIONED BY (day_id STRING)
|
||||
STORED AS ORC
|
||||
TBLPROPERTIES (
|
||||
'orc.compress' = 'SNAPPY', -- 压缩格式
|
||||
'orc.create.index' = 'true', -- 创建索引
|
||||
'transactional' = 'false' -- 非事务表
|
||||
);
|
||||
|
||||
-- ============================================================================
|
||||
-- 场景7:Parquet 格式
|
||||
-- ============================================================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS db_name.parquet_table (
|
||||
id BIGINT COMMENT '主键ID',
|
||||
name STRING COMMENT '名称',
|
||||
amount DECIMAL(18,2) COMMENT '金额',
|
||||
tags ARRAY<STRING> COMMENT '标签数组',
|
||||
props MAP<STRING,STRING> COMMENT '属性映射'
|
||||
)
|
||||
COMMENT 'Parquet格式表示例'
|
||||
PARTITIONED BY (day_id STRING)
|
||||
STORED AS PARQUET
|
||||
TBLPROPERTIES (
|
||||
'parquet.compression' = 'SNAPPY'
|
||||
);
|
||||
|
||||
-- ============================================================================
|
||||
-- 场景8:临时表
|
||||
-- ============================================================================
|
||||
|
||||
-- 会话级临时表(会话结束自动删除)
|
||||
CREATE TEMPORARY TABLE tmp_processing (
|
||||
id BIGINT,
|
||||
name STRING,
|
||||
amount DECIMAL(18,2)
|
||||
);
|
||||
|
||||
-- CTAS 快速创建临时表
|
||||
CREATE TEMPORARY TABLE tmp_source AS
|
||||
SELECT id, name, amount
|
||||
FROM source_table
|
||||
WHERE day_id = '${day_id}';
|
||||
|
||||
-- ============================================================================
|
||||
-- 字段类型速查
|
||||
-- ============================================================================
|
||||
/*
|
||||
| 类型 | 说明 | 适用场景 |
|
||||
|-------------------|----------------|------------------------|
|
||||
| TINYINT | 1字节整数 | 小范围数值 |
|
||||
| SMALLINT | 2字节整数 | 小范围数值 |
|
||||
| INT | 4字节整数 | 数量、等级 |
|
||||
| BIGINT | 8字节整数 | ID、计数 |
|
||||
| FLOAT | 4字节浮点 | 近似计算 |
|
||||
| DOUBLE | 8字节浮点 | 科学计算 |
|
||||
| DECIMAL(p,s) | 定点数 | 金额、精确数值 |
|
||||
| BOOLEAN | 布尔 | 状态标志 |
|
||||
| STRING | 变长字符串 | 名称、描述(最常用) |
|
||||
| VARCHAR(n) | 变长字符串 | 限定长度字符串 |
|
||||
| CHAR(n) | 定长字符串 | 固定长度编码 |
|
||||
| DATE | 日期 | 日期字段 |
|
||||
| TIMESTAMP | 时间戳 | 时间字段 |
|
||||
| BINARY | 二进制 | 二进制数据 |
|
||||
| ARRAY<type> | 数组 | 多值字段 |
|
||||
| MAP<k,v> | 映射 | 属性字典 |
|
||||
| STRUCT<f1:t1,...> | 结构体 | 嵌套结构 |
|
||||
*/
|
||||
|
||||
-- ============================================================================
|
||||
-- 建表规范说明
|
||||
-- ============================================================================
|
||||
/*
|
||||
1. 内部表 vs 外部表
|
||||
- 内部表:Hive 管理数据,DROP 删数据和元数据
|
||||
- 外部表:外部管理数据,DROP 只删元数据
|
||||
- 生产推荐:原始数据用外部表,加工结果用内部表
|
||||
|
||||
2. 存储格式选择
|
||||
- ORC(推荐):压缩好,列存储,支持谓词下推
|
||||
- PARQUET:跨平台兼容好,列存储
|
||||
- TEXTFILE:原始数据导入,性能最差
|
||||
|
||||
3. 分区设计
|
||||
- 按时间分区最常用(day_id, month_id)
|
||||
- 分区列不能出现在表定义的列中(Hive 特有)
|
||||
- 查询时分区列作为普通字段使用
|
||||
|
||||
4. 分桶设计
|
||||
- 选择高基数列做分桶列
|
||||
- 用于优化 JOIN(分桶列相同可做 map-side join)
|
||||
- 用于数据抽样(TABLESAMPLE)
|
||||
|
||||
5. 字段命名规范
|
||||
- snake_case 格式:user_id, total_amount
|
||||
- 主键:id 或 {业务}_id
|
||||
- 技术字段:etl_time, etl_remark
|
||||
- 分区字段:day_id, month_id, year_id
|
||||
|
||||
6. COMMENT 必须添加
|
||||
- 每个字段必须有 COMMENT
|
||||
- 表必须有 COMMENT
|
||||
*/
|
||||
@@ -0,0 +1,138 @@
|
||||
-- =====================================================================
|
||||
-- @Name: HIVE-D-SQL-{表名}-ETL
|
||||
-- @Version: 1.0
|
||||
-- @Desc: Hive ETL 数据处理模板(临时表链式处理)
|
||||
-- @TargetDatabase: Hive
|
||||
-- @说明: 和 Spark 类似,禁止 CTE,每步物化为临时表
|
||||
-- =====================================================================
|
||||
|
||||
-- ============================================================================
|
||||
-- Step01: 基础清洗与过滤
|
||||
-- ============================================================================
|
||||
-- 说明:从源表读取数据,进行基础过滤和清洗
|
||||
-- 输入:{源表名}
|
||||
-- 输出:tmp_etl_01
|
||||
|
||||
DROP TABLE IF EXISTS ${db_tmp_env}.tmp_xxx_01;
|
||||
CREATE TABLE ${db_tmp_env}.tmp_xxx_01 AS
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
amount,
|
||||
status,
|
||||
dept_id,
|
||||
category_id,
|
||||
created_at,
|
||||
day_id
|
||||
FROM db_name.source_table
|
||||
WHERE day_id = '${day_id}' -- 分区过滤(必须)
|
||||
AND status IN ('active', 'valid') -- 业务过滤
|
||||
AND amount > 0 -- 数据质量过滤
|
||||
AND id IS NOT NULL; -- NULL过滤
|
||||
|
||||
-- ============================================================================
|
||||
-- Step02: 多表关联与维度补全
|
||||
-- ============================================================================
|
||||
-- 说明:关联维度表,补全业务属性字段
|
||||
-- 输入:tmp_xxx_01, dim_department, dim_category
|
||||
-- 输出:tmp_xxx_02
|
||||
|
||||
DROP TABLE IF EXISTS ${db_tmp_env}.tmp_xxx_02;
|
||||
CREATE TABLE ${db_tmp_env}.tmp_xxx_02 AS
|
||||
SELECT
|
||||
a.id,
|
||||
a.name,
|
||||
a.amount,
|
||||
a.status,
|
||||
b.dept_name, -- 维度补全:部门名称
|
||||
c.category_name, -- 维度补全:类别名称
|
||||
a.created_at,
|
||||
a.day_id
|
||||
FROM ${db_tmp_env}.tmp_xxx_01 a
|
||||
LEFT JOIN db_name.dim_department b
|
||||
ON a.dept_id = b.dept_id
|
||||
AND b.day_id = '${day_id}' -- 维度表分区过滤
|
||||
LEFT JOIN db_name.dim_category c
|
||||
ON a.category_id = c.category_id
|
||||
AND c.day_id = '${day_id}'; -- 维度表分区过滤
|
||||
|
||||
-- ============================================================================
|
||||
-- Step03: 聚合计算与指标生成
|
||||
-- ============================================================================
|
||||
-- 说明:按业务维度聚合,计算统计指标
|
||||
-- 输入:tmp_xxx_02
|
||||
-- 输出:tmp_xxx_03
|
||||
|
||||
DROP TABLE IF EXISTS ${db_tmp_env}.tmp_xxx_03;
|
||||
CREATE TABLE ${db_tmp_env}.tmp_xxx_03 AS
|
||||
SELECT
|
||||
day_id,
|
||||
dept_name,
|
||||
category_name,
|
||||
COUNT(*) AS record_count, -- 记录数
|
||||
COUNT(DISTINCT id) AS unique_count, -- 唯一计数
|
||||
SUM(amount) AS total_amount, -- 总金额
|
||||
AVG(amount) AS avg_amount, -- 平均金额
|
||||
MAX(amount) AS max_amount, -- 最大金额
|
||||
MIN(amount) AS min_amount -- 最小金额
|
||||
FROM ${db_tmp_env}.tmp_xxx_02
|
||||
GROUP BY day_id, dept_name, category_name;
|
||||
|
||||
-- ============================================================================
|
||||
-- Step04: 最终输出写入目标表
|
||||
-- ============================================================================
|
||||
-- 说明:补全目标表标准字段,写入结果表
|
||||
-- 输入:tmp_xxx_03
|
||||
-- 输出:目标表
|
||||
|
||||
INSERT OVERWRITE TABLE ${db_eda_env}.target_table
|
||||
PARTITION (day_id = '${day_id}')
|
||||
SELECT
|
||||
-- 业务字段
|
||||
dept_name,
|
||||
category_name,
|
||||
record_count,
|
||||
unique_count,
|
||||
total_amount,
|
||||
avg_amount,
|
||||
max_amount,
|
||||
min_amount,
|
||||
|
||||
-- 技术字段
|
||||
current_timestamp() AS etl_time, -- 数据加工时间
|
||||
'${day_id}' AS stat_date; -- 统计日期
|
||||
|
||||
-- ============================================================================
|
||||
-- 关键规则说明
|
||||
-- ============================================================================
|
||||
/*
|
||||
1. 禁止使用 CTE (WITH 子句)
|
||||
- 每个步骤必须物化为临时表
|
||||
- 原因:Hive CTE 可能在某些版本有性能问题
|
||||
- 物化临时表便于调试和断点续跑
|
||||
|
||||
2. 先 DROP 再 CREATE
|
||||
- 每个临时表创建前必须先 DROP TABLE IF EXISTS
|
||||
- 原因:防止表已存在导致失败
|
||||
|
||||
3. 分区过滤必须前置
|
||||
- 所有源表和维度表查询必须带 day_id 过滤
|
||||
- 原因:避免全表扫描,提升性能
|
||||
|
||||
4. JOIN 条件下推
|
||||
- 维度表关联时带上分区过滤条件
|
||||
- 原因:减少关联数据量
|
||||
|
||||
5. 临时表命名规范
|
||||
- 格式:tmp_{业务简称}_{步骤序号}
|
||||
- 示例:tmp_order_stats_01, tmp_order_stats_02
|
||||
|
||||
6. 目标表写入规范
|
||||
- 使用 INSERT OVERWRITE(覆盖写入,幂等)
|
||||
- 明确指定分区
|
||||
- 补全技术字段(etl_time 等)
|
||||
|
||||
7. 存储格式建议
|
||||
- 临时表:默认格式即可(中间结果不需要优化存储)
|
||||
- 如需优化:STORED AS ORC
|
||||
*/
|
||||
@@ -0,0 +1,141 @@
|
||||
-- =====================================================================
|
||||
-- @Name: HIVE-D-SQL-{表名}-INSERT
|
||||
-- @Version: 1.0
|
||||
-- @Desc: Hive 数据插入模板
|
||||
-- @TargetDatabase: Hive
|
||||
-- =====================================================================
|
||||
|
||||
-- ============================================================================
|
||||
-- 场景1:分区表覆盖写入(最常用)
|
||||
-- ============================================================================
|
||||
-- 适用:每日/每周/每月增量写入分区表
|
||||
|
||||
INSERT OVERWRITE TABLE db_name.target_table
|
||||
PARTITION (day_id = '${day_id}')
|
||||
SELECT
|
||||
user_id,
|
||||
user_name,
|
||||
order_count,
|
||||
total_amount,
|
||||
current_timestamp() AS etl_time
|
||||
FROM db_name.source_table
|
||||
WHERE day_id = '${day_id}';
|
||||
|
||||
-- ============================================================================
|
||||
-- 场景2:动态分区写入
|
||||
-- ============================================================================
|
||||
-- 适用:数据中包含分区值,自动写入对应分区
|
||||
|
||||
-- 先启用动态分区
|
||||
SET hive.exec.dynamic.partition = true;
|
||||
SET hive.exec.dynamic.partition.mode = nonstrict;
|
||||
|
||||
INSERT OVERWRITE TABLE db_name.target_table
|
||||
PARTITION (day_id, region) -- 动态分区字段
|
||||
SELECT
|
||||
user_id,
|
||||
user_name,
|
||||
order_count,
|
||||
total_amount,
|
||||
current_timestamp() AS etl_time,
|
||||
day_id, -- 分区字段1(数据中包含)
|
||||
region -- 分区字段2(数据中包含)
|
||||
FROM db_name.source_table
|
||||
WHERE day_id BETWEEN '${start_day}' AND '${end_day}';
|
||||
|
||||
-- ============================================================================
|
||||
-- 场景3:追加写入
|
||||
-- ============================================================================
|
||||
-- 适用:日志表、流水表(允许追加)
|
||||
|
||||
INSERT INTO TABLE db_name.target_table
|
||||
SELECT
|
||||
field1,
|
||||
field2,
|
||||
field3,
|
||||
current_timestamp() AS etl_time
|
||||
FROM db_name.source_table
|
||||
WHERE day_id = '${day_id}';
|
||||
|
||||
-- ============================================================================
|
||||
-- 场景4:多分区插入(Multi-Insert)
|
||||
-- ============================================================================
|
||||
-- 适用:一次扫描,写入多个目标(提高效率)
|
||||
|
||||
FROM db_name.source_table
|
||||
INSERT OVERWRITE TABLE db_name.target_summary
|
||||
PARTITION (day_id = '${day_id}')
|
||||
SELECT
|
||||
department,
|
||||
COUNT(*) AS record_count,
|
||||
SUM(amount) AS total_amount
|
||||
WHERE day_id = '${day_id}'
|
||||
GROUP BY department
|
||||
|
||||
INSERT OVERWRITE TABLE db_name.target_detail
|
||||
PARTITION (day_id = '${day_id}')
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
amount,
|
||||
department
|
||||
WHERE day_id = '${day_id}'
|
||||
AND amount > 1000;
|
||||
|
||||
-- ============================================================================
|
||||
-- 场景5:导出到文件
|
||||
-- ============================================================================
|
||||
|
||||
INSERT OVERWRITE DIRECTORY '/output/data/export/'
|
||||
ROW FORMAT DELIMITED
|
||||
FIELDS TERMINATED BY ','
|
||||
STORED AS TEXTFILE
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
amount,
|
||||
day_id
|
||||
FROM db_name.target_table
|
||||
WHERE day_id = '${day_id}';
|
||||
|
||||
-- ============================================================================
|
||||
-- 场景6:CTAS(Create Table As Select)
|
||||
-- ============================================================================
|
||||
|
||||
-- 从查询结果创建新表
|
||||
CREATE TABLE db_name.new_table AS
|
||||
SELECT
|
||||
department,
|
||||
COUNT(*) AS employee_count,
|
||||
AVG(salary) AS avg_salary
|
||||
FROM db_name.employees
|
||||
WHERE day_id = '${day_id}'
|
||||
GROUP BY department;
|
||||
|
||||
-- ============================================================================
|
||||
-- 关键规则说明
|
||||
-- ============================================================================
|
||||
/*
|
||||
1. INSERT OVERWRITE vs INSERT INTO
|
||||
- INSERT OVERWRITE:覆盖分区/表数据(推荐,幂等)
|
||||
- INSERT INTO:追加数据(可能产生重复)
|
||||
|
||||
2. 分区表写入必须指定分区
|
||||
- 静态分区:PARTITION (day_id = '${day_id}')
|
||||
- 动态分区:需先 SET 配置,PARTITION (day_id)
|
||||
- 混合分区:PARTITION (day_id = '2026-05-01', region)
|
||||
|
||||
3. 动态分区配置
|
||||
SET hive.exec.dynamic.partition = true;
|
||||
SET hive.exec.dynamic.partition.mode = nonstrict; -- 允许全动态
|
||||
SET hive.exec.max.dynamic.partitions = 1000; -- 最大动态分区数
|
||||
|
||||
4. 字段顺序
|
||||
- SELECT 字段顺序必须与目标表列定义一致
|
||||
- 分区字段在 SELECT 最后(动态分区时)
|
||||
|
||||
5. 性能优化
|
||||
- 多分区插入(Multi-Insert):一次扫描多次写入
|
||||
- INSERT OVERWRITE 比 INSERT INTO 更安全(幂等性)
|
||||
- 大数据量写入时注意 reducer 数量设置
|
||||
*/
|
||||
@@ -0,0 +1,235 @@
|
||||
-- =====================================================================
|
||||
-- @Name: HIVE-D-SQL-{表名}-QUERY
|
||||
-- @Version: 1.0
|
||||
-- @Desc: Hive 查询模板
|
||||
-- @TargetDatabase: Hive
|
||||
-- =====================================================================
|
||||
|
||||
-- ============================================================================
|
||||
-- 1. 单表查询
|
||||
-- ============================================================================
|
||||
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
amount,
|
||||
created_at
|
||||
FROM db_name.source_table
|
||||
WHERE day_id = '${day_id}' -- 分区过滤(必须)
|
||||
AND status = 'active'
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 1000;
|
||||
|
||||
-- ============================================================================
|
||||
-- 2. JOIN 查询
|
||||
-- ============================================================================
|
||||
|
||||
-- 两表 JOIN
|
||||
SELECT
|
||||
a.id,
|
||||
a.name,
|
||||
a.amount,
|
||||
b.category_name
|
||||
FROM db_name.main_table a
|
||||
JOIN db_name.dim_table b ON a.category_id = b.id
|
||||
WHERE a.day_id = '${day_id}';
|
||||
|
||||
-- 多表 JOIN(带别名)
|
||||
SELECT
|
||||
o.order_id,
|
||||
u.user_name,
|
||||
p.product_name,
|
||||
oi.quantity,
|
||||
oi.unit_price
|
||||
FROM db_name.orders o
|
||||
JOIN db_name.users u ON o.user_id = u.id
|
||||
JOIN db_name.order_items oi ON o.order_id = oi.order_id
|
||||
JOIN db_name.products p ON oi.product_id = p.id
|
||||
WHERE o.day_id = '${day_id}'
|
||||
AND o.status IN ('completed', 'shipped');
|
||||
|
||||
-- ============================================================================
|
||||
-- 3. 聚合查询
|
||||
-- ============================================================================
|
||||
|
||||
-- GROUP BY + HAVING
|
||||
SELECT
|
||||
department,
|
||||
COUNT(*) AS employee_count,
|
||||
SUM(salary) AS total_salary,
|
||||
AVG(salary) AS avg_salary,
|
||||
MAX(salary) AS max_salary
|
||||
FROM db_name.employees
|
||||
WHERE day_id = '${day_id}'
|
||||
GROUP BY department
|
||||
HAVING COUNT(*) >= 5
|
||||
ORDER BY total_salary DESC;
|
||||
|
||||
-- 多字段分组 + 去重计数
|
||||
SELECT
|
||||
date,
|
||||
region,
|
||||
COUNT(*) AS order_count,
|
||||
COUNT(DISTINCT user_id) AS unique_users,
|
||||
SUM(amount) AS total_amount
|
||||
FROM db_name.orders
|
||||
WHERE day_id = '${day_id}'
|
||||
GROUP BY date, region;
|
||||
|
||||
-- ============================================================================
|
||||
-- 4. 窗口函数
|
||||
-- ============================================================================
|
||||
|
||||
-- ROW_NUMBER(分组取Top N)
|
||||
SELECT *
|
||||
FROM (
|
||||
SELECT
|
||||
department,
|
||||
name,
|
||||
salary,
|
||||
ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS rn
|
||||
FROM db_name.employees
|
||||
WHERE day_id = '${day_id}'
|
||||
) t
|
||||
WHERE rn <= 3;
|
||||
|
||||
-- 累计聚合
|
||||
SELECT
|
||||
date,
|
||||
amount,
|
||||
SUM(amount) OVER (ORDER BY date) AS cumulative_amount,
|
||||
AVG(amount) OVER (
|
||||
ORDER BY date
|
||||
ROWS BETWEEN 6 PRECEDING AND CURRENT ROW
|
||||
) AS moving_avg_7d
|
||||
FROM daily_sales
|
||||
WHERE day_id = '${day_id}';
|
||||
|
||||
-- LAG/LEAD(环比)
|
||||
SELECT
|
||||
date,
|
||||
amount,
|
||||
LAG(amount, 1) OVER (ORDER BY date) AS prev_amount,
|
||||
amount - LAG(amount, 1) OVER (ORDER BY date) AS daily_change
|
||||
FROM daily_sales
|
||||
WHERE day_id = '${day_id}';
|
||||
|
||||
-- ============================================================================
|
||||
-- 5. 子查询
|
||||
-- ============================================================================
|
||||
|
||||
-- IN 子查询
|
||||
SELECT *
|
||||
FROM db_name.orders
|
||||
WHERE user_id IN (
|
||||
SELECT id FROM db_name.users WHERE vip_level >= 3
|
||||
)
|
||||
AND day_id = '${day_id}';
|
||||
|
||||
-- EXISTS 子查询
|
||||
SELECT *
|
||||
FROM db_name.products p
|
||||
WHERE EXISTS (
|
||||
SELECT 1 FROM db_name.inventory i
|
||||
WHERE i.product_id = p.id
|
||||
AND i.quantity > 0
|
||||
)
|
||||
AND p.day_id = '${day_id}';
|
||||
|
||||
-- ============================================================================
|
||||
-- 6. 条件聚合(CASE WHEN + 聚合)
|
||||
-- ============================================================================
|
||||
|
||||
SELECT
|
||||
date,
|
||||
COUNT(*) AS total_orders,
|
||||
SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) AS completed_count,
|
||||
SUM(CASE WHEN status = 'cancelled' THEN 1 ELSE 0 END) AS cancelled_count,
|
||||
SUM(CASE WHEN amount > 1000 THEN amount ELSE 0 END) AS high_value_amount
|
||||
FROM db_name.orders
|
||||
WHERE day_id = '${day_id}'
|
||||
GROUP BY date;
|
||||
|
||||
-- ============================================================================
|
||||
-- 7. LATERAL VIEW + explode(Hive 特有)
|
||||
-- ============================================================================
|
||||
|
||||
-- 展开数组字段
|
||||
SELECT
|
||||
id,
|
||||
name,
|
||||
tag
|
||||
FROM db_name.articles
|
||||
LATERAL VIEW explode(tags) t AS tag
|
||||
WHERE day_id = '${day_id}';
|
||||
|
||||
-- 展开数组并统计
|
||||
SELECT
|
||||
tag,
|
||||
COUNT(*) AS article_count
|
||||
FROM db_name.articles
|
||||
LATERAL VIEW explode(tags) t AS tag
|
||||
WHERE day_id = '${day_id}'
|
||||
GROUP BY tag;
|
||||
|
||||
-- 展开 Map
|
||||
SELECT
|
||||
id,
|
||||
map_key,
|
||||
map_value
|
||||
FROM db_name.data_table
|
||||
LATERAL VIEW explode(props) m AS map_key, map_value
|
||||
WHERE day_id = '${day_id}';
|
||||
|
||||
-- posexplode(带索引展开)
|
||||
SELECT
|
||||
id,
|
||||
pos,
|
||||
tag
|
||||
FROM db_name.articles
|
||||
LATERAL VIEW posexplode(tags) t AS pos, tag
|
||||
WHERE day_id = '${day_id}';
|
||||
|
||||
-- ============================================================================
|
||||
-- 8. 复杂类型查询
|
||||
-- ============================================================================
|
||||
|
||||
-- ARRAY 操作
|
||||
SELECT
|
||||
id,
|
||||
size(tags) AS tag_count, -- 数组长度
|
||||
array_contains(tags, '大数据') AS has_tag, -- 包含判断
|
||||
tags[0] AS first_tag -- 取第一个元素
|
||||
FROM db_name.articles
|
||||
WHERE day_id = '${day_id}';
|
||||
|
||||
-- MAP 操作
|
||||
SELECT
|
||||
id,
|
||||
props['city'] AS city, -- 取值
|
||||
map_keys(props) AS all_keys, -- 所有 key
|
||||
map_values(props) AS all_values -- 所有 value
|
||||
FROM db_name.user_table
|
||||
WHERE day_id = '${day_id}';
|
||||
|
||||
-- STRUCT 操作
|
||||
SELECT
|
||||
id,
|
||||
user_info.name AS user_name, -- 结构体字段访问
|
||||
user_info.age AS user_age
|
||||
FROM db_name.data_table
|
||||
WHERE day_id = '${day_id}';
|
||||
|
||||
-- ============================================================================
|
||||
-- 9. 集合聚合
|
||||
-- ============================================================================
|
||||
|
||||
-- collect_list / collect_set
|
||||
SELECT
|
||||
department,
|
||||
collect_list(name) AS all_names, -- 收集为数组(不去重)
|
||||
collect_set(name) AS unique_names, -- 收集为数组(去重)
|
||||
size(collect_set(name)) AS unique_count
|
||||
FROM db_name.employees
|
||||
WHERE day_id = '${day_id}'
|
||||
GROUP BY department;
|
||||
Reference in New Issue
Block a user