如何在HiveQL中获取当前级别、历史级别及升降级标识
当然可以用单条查询实现!问题出在排序逻辑上——你按End_dt降序排名时,虽然能定位到最新记录,但要正确关联历史级别,得先按时间顺序(从旧到新)排列,再用窗口函数抓取上一级别的信息。
先理清楚你的源数据
首先把你给出的源数据整理成更直观的表格:
| ID | Level | start_dt | End_dt |
|---|---|---|---|
| A | 1 | 2018-03-12 18:39:10 | 2020-01-01 00:00:00 |
| A | 1 | 2018-01-17 13:21:26 | 2018-03-12 18:39:10 |
| A | 2 | 2018-01-14 13:21:17 | 2018-01-17 13:21:26 |
单条查询实现方案
这里用支持窗口函数的SQL语法(MySQL 8+、PostgreSQL、SQL Server等都适用),核心思路是:按ID分组,按时间顺序排列记录,用LAG()函数获取上一级别,再筛选出最新记录作为当前级别,同时生成升降级标记。
WITH level_history AS ( SELECT ID, Level, -- 按时间从旧到新给每个ID的记录排名,最大的rn对应最新记录 ROW_NUMBER() OVER (PARTITION BY ID ORDER BY start_dt ASC) AS rn, -- 抓取上一个时间点的级别 LAG(Level) OVER (PARTITION BY ID ORDER BY start_dt ASC) AS previous_level FROM your_table_name ) SELECT ID, Level AS current_level, previous_level, -- 判断升降级逻辑 CASE WHEN Level > previous_level THEN 'upgrade' WHEN Level < previous_level THEN 'downgrade' ELSE 'no_change' END AS upgrade_downgrade_flag FROM level_history -- 只保留每个ID的最新记录 WHERE rn = (SELECT MAX(rn) FROM level_history WHERE ID = level_history.ID);
查询逻辑解释
- CTE部分:
level_history里用ROW_NUMBER()按start_dt升序给每个ID的记录排序,最早的记录rn=1,最新的记录rn值最大;同时用LAG()函数自动抓取当前记录的上一条(时间更早的)级别值。 - 外层查询:筛选出每个ID的最新记录(
rn最大的那条),再通过CASE语句判断当前级别相对历史级别的变化。
针对你的数据,执行后会得到结果:
| ID | current_level | previous_level | upgrade_downgrade_flag |
|---|---|---|---|
| A | 1 | 1 | no_change |
拓展:展示所有级别变化历史
如果你想一次性看到所有历史级别的变化(而不只是当前级别),可以去掉外层的WHERE条件,修改成:
SELECT ID, Level AS current_level, previous_level, CASE WHEN previous_level IS NULL THEN 'initial_level' WHEN Level > previous_level THEN 'upgrade' WHEN Level < previous_level THEN 'downgrade' ELSE 'no_change' END AS upgrade_downgrade_flag FROM ( SELECT ID, Level, LAG(Level) OVER (PARTITION BY ID ORDER BY start_dt ASC) AS previous_level FROM your_table_name ) AS history;
这个版本会返回所有历史记录的级别变化,第一条记录因为没有前置级别,会标记为initial_level。
内容的提问来源于stack exchange,提问作者Anil Kulkarni
相关产品推荐
相关产品推荐

