如何按日期筛选每日首条数据(SQL实现)
嘿,我来帮你搞定这个问题!先理清楚你的核心需求:从temp表的指定日期范围内,每天只返回一条ID记录(看你的期望结果,是每个日期取最小的ID对吧?)。
先把你的表结构、参数和期望结果整理得更直观:
原表结构 (temp)
| temp ID | Date |
|---|---|
| 1 | 2018-01-01 |
| 2 | 2018-01-01 |
| 3 | 2018-01-01 |
| 4 | 2018-01-02 |
| 5 | 2018-01-02 |
| 6 | 2018-01-03 |
输入参数
@StartDate DATE = '2018-01-01' @EndDate DATE = '2018-01-03'
期望结果
| ID | Date |
|---|---|
| 1 | 2018-01-01 |
| 4 | 2018-01-02 |
| 6 | 2018-01-03 |
先分析你之前的查询问题
你的自连接逻辑走偏了:子查询里按innerTemp.ID和innerTemp.Date分组,这其实每个分组就是单条记录(因为每个ID对应唯一的Date),所以子查询返回的还是所有符合日期条件的行,后续的自连接和distinct自然没法帮你筛选出每日一条的结果。
两个可行的解决方案
方案一:GROUP BY + 聚合函数(最简单直接)
既然你需要每个日期对应一个ID,直接按Date分组,用MIN(ID)(取当天最小ID,完全匹配你的期望)或者MAX(ID)(取当天最大ID)聚合即可:
SELECT MIN(ID) AS ID, Date FROM temp WHERE Date >= @StartDate AND Date <= @EndDate GROUP BY Date ORDER BY Date ASC;
这个查询性能优异,适合这种简单的分组取数场景,执行后就能得到你想要的结果。
方案二:窗口函数(更灵活,适配复杂场景)
如果之后你需要返回更多字段,或者有更复杂的筛选规则(比如按创建时间取最新记录),可以用ROW_NUMBER()窗口函数:
WITH RankedData AS ( SELECT ID, Date, -- 按Date分区,每个分区内按ID升序编号,最小的ID会得到rn=1 ROW_NUMBER() OVER (PARTITION BY Date ORDER BY ID ASC) AS rn FROM temp WHERE Date >= @StartDate AND Date <= @EndDate ) SELECT ID, Date FROM RankedData WHERE rn = 1 ORDER BY Date ASC;
这个方案扩展性极强——比如你之后要取每个日期最后插入的记录,只需要把ORDER BY ID ASC改成ORDER BY CreateTime DESC就行,非常灵活。
内容的提问来源于stack exchange,提问作者Zach
相关产品推荐
相关产品推荐

