【SQL】比「昨天」溫度還高的紀錄

這題是 LeetCode 上的 SQL 題目 197. Rising Temperature,任務是:

找出氣溫比「昨天」更高的日期紀錄。

題目

找出與前一天(昨天)相比溫度更高的所有日期的ID。以任意順序傳回結果表。

Table: Weather

Column Name Type
id int
recordDate date
temperature int

請參考以下範例:

Input: Weather table
id recordDate temperature
1 2015-01-01 10
2 2015-01-02 25
3 2015-01-03 20
4 2015-01-04 30
Output:
id
2
4

解釋說明:

  • 2015-01-02 溫度比前一天 (2015-01-01) 高 (25 > 10)。
  • 2015-01-04 溫度比前一天 (2015-01-03) 高 (30 > 20)。

解法

解題核心觀念: 自己JOIN自己。

Self Join

  • Weather表取兩份表,取名為todayyesterday
  • today的資料,和前一天yesterday的資料配對起來。
1
2
FROM Weather today
JOIN Weather yesterday

算日期差

  • DATEDIFF()算日期差。
  • DATEDIFF(a, b)a - b,我們希望today - yesterday = 1,代表today是比yesterday晚一天。
  • DATEDIFF(today.recordDate, yesterday.recordDate) = 1意思即是today.recordDate - yesterday.recordDate = 1,所以如果差一,我們就可以得到今天跟昨天的配對資料。
1
JOIN Weather yesterday ON DATEDIFF(today.recordDate, yesterday.recordDate) = 1

怎麼配對資料呢?

today表和yesterday表中recordDate的所有資料,兩兩配對起來。

today.recordDate yesterday.recordDate DATEDIFF()
2015-01-01 2015-01-01 0
2015-01-01 2015-01-02 -1
2015-01-01 2015-01-03 -2
2015-01-01 2015-01-04 -3
2015-01-02 2015-01-01 1 ✅ ←選中這個組合
2015-01-02 2015-01-02 0
2015-01-02 2015-01-03 -1
2015-01-02 2015-01-04 -2
2015-01-03 2015-01-01 2
2015-01-03 2015-01-02 1 ✅ ←選中這個組合
2015-01-03 2015-01-03 0
2015-01-03 2015-01-04 -1
2015-01-04 2015-01-01 3
2015-01-04 2015-01-02 2
2015-01-04 2015-01-03 1 ✅ ←選中這個組合
2015-01-04 2015-01-04 0

然後只留下「差一天」的組合

today.recordDate yesterday.recordDate DATEDIFF()
2015-01-02 2015-01-01 1 ✅ ←選中這個組合
2015-01-03 2015-01-02 1 ✅ ←選中這個組合
2015-01-04 2015-01-03 1 ✅ ←選中這個組合

比較溫度

WHERE篩選出today溫度比yesterday溫度高的紀錄。

1
WHERE today.temperature > yesterday.temperature
today
id
today
recordDate
today
temperature
yesterday
recordDate
yesterday
temperature
比較溫度 是否保留
2 2015-01-02 25 2015-01-01 10 25 > 10
3 2015-01-03 20 2015-01-02 25 20 < 25
4 2015-01-04 30 2015-01-03 20 30 > 20

選出id

最後只要回傳todayid就可以了。

1
SELECT today.id
id
2
4

完整程式碼

1
2
3
4
SELECT today.id
FROM Weather today
JOIN Weather yesterday ON DATEDIFF(today.recordDate, yesterday.recordDate) = 1
WHERE today.temperature > yesterday.temperature
Input: Weather table
id recordDate temperature
1 2015-01-01 10
2 2015-01-02 25
3 2015-01-03 20
4 2015-01-04 30
Output:
id
2
4