比昨天温度高的日期:相邻日期要真的相差一天
LeetCode 197 · LAG、日期差、自连接
面试怎么回答
关键是「昨天」按日历算,不是按行算。我会用自连接 DATEDIFF(w1.RecordDate, w2.RecordDate) = 1 关联前一天再比较温度;用 LAG 的话也要额外校验日期差为 1,否则缺数据的日子会拿前天的值来比。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
题意
天气表每天一条记录,找出温度比前一天高的记录 Id。注意记录日期可能不连续,「前一天」指的是日历上的昨天,不是表里的上一行。
表结构
- Weather:Id(主键)、RecordDate(日期)、Temperature
思路
用 LAG 按日期取上一条记录的日期和温度,同时校验两条记录的日期差正好是 1 天,才算「昨天」。原解法里给 LAG 设的默认值只是为了让第一行不满足条件;更清楚的写法是不设默认值,第一行拿到 NULL,比较结果为未知自然被过滤。
参考解法
select
Id
from
(
select Id,RecordDate,Temperature,
lag(RecordDate,1,9999-99-99) over (order by RecordDate) yd,
lag(Temperature,1,999) over(order by RecordDate ) yt
from Weather
)tmp
where Temperature >yt
and datediff(RecordDate,yd)=1
另一种写法:自连接写法,直接按「日期差 1 天」关联
SELECT w1.Id
FROM Weather w1
JOIN Weather w2 ON DATEDIFF(w1.RecordDate, w2.RecordDate) = 1
WHERE w1.Temperature > w2.Temperature
易错点
- 只比较「上一行」不检查日期差:中间缺一天时,会拿前天的温度来比。
- 原解法中
9999-99-99没加引号,会被当成算术表达式,只是碰巧不影响结果;默认值不需要设置。