题目
给定一个 Weather 表,编写一个 SQL 查询,来查找与之前(昨天的)日期相比温度更高的所有日期的 Id。
+---------+------------------+------------------+
| Id(INT) | RecordDate(DATE) | Temperature(INT) |
+---------+------------------+------------------+
| 1 | 2015-01-01 | 10 |
| 2 | 2015-01-02 | 25 |
| 3 | 2015-01-03 | 20 |
| 4 | 2015-01-04 | 30 |
+---------+------------------+------------------+
例如,根据上述给定的 Weather 表格,返回如下 Id:
+----+
| Id |
+----+
| 2 |
| 4 |
+----+
审题
没必要
生成数据
CREATE TABLE Weather(
Id INT,
RecordDate DATE,
Temperature INT );
INSERT INTO Weather VALUE(1,'2015-01-01',10),(2,'2015-01-02',25),(3,'2015-01-03',20),(4,'2015-01-04',30),(5,'2015-01-31',100);
SELECT *
FROM Weather;
这里加了第五行日期为0131 是为了说明之后的一个问题。
自己的解答
表的自连接就可以做的
一个表当做昨天(yesterday)表,一个表当做今天(today)表,根据今天的日期是昨天的日期+1进行连接,再比较两个温度即可。
SELECT tod.`Id` AS Id
FROM Weather yes
LEFT JOIN Weather tod
ON yes.`RecordDate` = tod.`RecordDate` - 1
WHERE tod.`Temperature` > yes.`Temperature` ;
针对这个数据集是没问题的,但是在leetcode上提交不通过。。。
一直想不明白为什么,后边才明白对于日期类型的数据一定要用对于日期内置的函数。
看下边的例子就明白了
SELECT RecordDate, RecordDate + 1
FROM Weather;
显然,简单的对日期函数进行处理是不行的0131+1得到的是0132 而不是想要的0201
注意:DATEDIFF是两个日期的天数差集
修正一下
SELECT tod.`Id` AS Id
FROM Weather yes
LEFT JOIN Weather tod
ON DATEDIFF(tod.`RecordDate`, yes.`RecordDate`) = 1
WHERE tod.`Temperature` > yes.`Temperature`
别的解答
1.类似的答案
函数: TIMESTAMPDIFF(unit,begin,end),返回begin与end之间相差多少个unit。unit为DAY时,即为相差“天”。
SELECT W2.Id
FROM weather AS W1 JOIN weather AS W2
ON (TIMESTAMPDIFF(DAY,W1.RecordDate,W2.RecordDate) = 1 AND W1.Temperature < W2.Temperature)
2.定义变量来解决
- @curd定义为当前日期
- @pred定义为前一天的日期
- @curt定义为当前温度
- @pret定义为前一天的温度
- @isH定义为是否满足条件
在from子句中赋初值
对每一行数据,给定当前日期和当前温度
@curd := w.RecordDate,
@curt := w.Temperature
判断当前温度和前一日温度的关系,大则取1,反之取0
这里需要对日期进行升序排序 个人认为排完序后datediff(@curd,@pred) = 1是多余的
可是日期不一定是连续的 而且会把最低天数对应的id选出来
因此还是不能去掉的
@isH := IF(DATEDIFF(@curd,@pred) = 1 AND @curt > @pret,1,0) AS r
再把当前温度及日期赋值给前一日温度及日期进行迭代
@pret := @curt,
@pred := @curd
合并:
select w.*,
@curd := w.RecordDate,
@curt := w.Temperature,
@isH := if(datediff(@curd,@pred) = 1 and @curt > @pret,1,0) as r,
@pret := @curt,
@pred := @curd
from
Weather w,
(select
@curd := null,
@pred := null,
@curt := 0,
@pret := 0,
@isH := 0
) init
order by w.RecordDate
结果:
最终把r为1的id选出来即可
SELECT
Id
FROM
(SELECT w.*,
@curd := w.RecordDate,
@curt := w.Temperature,
@isH := IF(DATEDIFF(@curd,@pred) = 1 AND @curt > @pret,1,0) AS r,
@pret := @curt,
@pred := @curd
FROM
Weather w,
(SELECT
@curd := NULL,
@pred := NULL,
@curt := 0,
@pret := 0,
@isH := 0
) init
ORDER BY w.RecordDate
) t
WHERE
t.r = 1