如何用SQL从快照表中提取按日期新增的行?是否需用窗口函数?
问题描述
我有如下快照表:
| id | name | value | date |
|---|---|---|---|
| 123 | ABC Corp | 500 | yesterday |
| 123 | ABC Corp | 500 | today |
| 456 | XYZ Ltd. | 700 | today |
| 123 | ABC Corp | 500 | tomorrow |
| 456 | XYZ Ltd. | 700 | tomorrow |
| 789 | PQR Consulting | 100 | tomorrow |
希望通过SQL从中获取仅包含新增行的结果集,预期结果如下:
| id | name | value | date |
|---|---|---|---|
| 456 | XYZ Ltd. | 700 | today |
| 789 | PQR Consulting | 100 | tomorrow |
想了解是否需要使用LAG()这类窗口函数来实现,或是存在更简便的解决方案。
解决方案
不需要依赖LAG()窗口函数,有两种实用方案可以实现需求:
方案一:分组提取首次出现的记录(更简便)
核心思路是定位每个id(若业务上id+name+value才是唯一标识,可调整分组字段)首次出现的日期,对应的记录就是新增行:
子查询+窗口函数版
SELECT id, name, value, date FROM ( SELECT id, name, value, date, MIN(date) OVER (PARTITION BY id) AS first_appear_date FROM your_table_name ) t WHERE date = first_appear_date;
分组聚合+关联版
SELECT t.id, t.name, t.value, t.date FROM your_table_name t INNER JOIN ( SELECT id, MIN(date) AS first_date FROM your_table_name GROUP BY id ) g ON t.id = g.id AND t.date = g.first_date;
方案二:使用LAG()窗口函数
如果需要对比相邻日期的记录逻辑,LAG()也能实现,但相对繁琐,适合复杂场景:
SELECT id, name, value, date FROM ( SELECT id, name, value, date, LAG(date) OVER (PARTITION BY id ORDER BY date) AS prev_date FROM your_table_name ) t WHERE prev_date IS NULL;
这里通过LAG()获取每个id按日期排序后的上一条记录日期,prev_date为NULL时,说明这是该id的第一条记录,即新增行。
总结
两种方案都能得到预期结果,分组提取首次记录的方式更简洁高效,数据量大时性能优势更明显。若业务中id并非唯一标识(比如name或value可能变动),只需将PARTITION BY或GROUP BY的字段调整为id, name, value即可准确识别新增的组合。
内容的提问来源于stack exchange,提问作者Neel
相关产品推荐
相关产品推荐

