題目
SQL架構
Create table If Not Exists stadium (id int, visit_date DATE NULL, people int)
Truncate table stadium
insert into stadium (id, visit_date, people) values ('1', '2017-01-01', '10')
insert into stadium (id, visit_date, people) values ('2', '2017-01-02', '109')
insert into stadium (id, visit_date, people) values ('3', '2017-01-03', '150')
insert into stadium (id, visit_date, people) values ('4', '2017-01-04', '99')
insert into stadium (id, visit_date, people) values ('5', '2017-01-05', '145')
insert into stadium (id, visit_date, people) values ('6', '2017-01-06', '1455')
insert into stadium (id, visit_date, people) values ('7', '2017-01-07', '199')
insert into stadium (id, visit_date, people) values ('8', '2017-01-08', '188')
X 市建了一個新的體育館,每日人流量信息被記錄在這三列信息中:序號 (id)、日期 (visit_date)、 人流量 (people)。
請編寫一個查詢語句,找出人流量的高峯期。高峯期時,至少連續三行記錄中的人流量不少於100。
例如,表 stadium:
+------+------------+-----------+
| id | visit_date | people |
+------+------------+-----------+
| 1 | 2017-01-01 | 10 |
| 2 | 2017-01-02 | 109 |
| 3 | 2017-01-03 | 150 |
| 4 | 2017-01-04 | 99 |
| 5 | 2017-01-05 | 145 |
| 6 | 2017-01-06 | 1455 |
| 7 | 2017-01-07 | 199 |
| 8 | 2017-01-08 | 188 |
+------+------------+-----------+
對於上面的示例數據,輸出爲:
+------+------------+-----------+
| id | visit_date | people |
+------+------------+-----------+
| 5 | 2017-01-05 | 145 |
| 6 | 2017-01-06 | 1455 |
| 7 | 2017-01-07 | 199 |
| 8 | 2017-01-08 | 188 |
+------+------------+-----------+
提示:
每天只有一行記錄,日期隨着 id 的增加而增加。
題解
如果只是找出全部人流量不少於100的記錄不難,難點在於如何查找連續的三天,一個想法是,查 3 張表,讓三個結果 id 連續
SELECT a.*
FROM stadium as a,stadium as b,stadium as c
where (a.id = b.id-1 and b.id+1 = c.id)
and (a.people>=100 and b.people>=100 and c.people>=100);
但是這樣輸出會有問題,比如 5,6,7,8 號人流量不少於100,但是隻輸出了 5,6號,根本原因在於,我們將 a 的 id 設爲三個連續值中最小值,所以只返回了每 3 個連續值中最小的一個,同理可想到,我們再將 a 的 id 設爲三個連續值中中間值和最大值,可以得到全部的連續 3 個值
SELECT a.*
FROM stadium as a,stadium as b,stadium as c
where ((a.id = b.id-1 and b.id+1 = c.id) or
(a.id-1 = b.id and a.id+1 = c.id) or
(a.id-1 = c.id and c.id-1 = b.id))
and (a.people>=100 and b.people>=100 and c.people>=100);
但是這樣還有個問題,比如 5,6,7,8,6 既是 5,6,7 的中間值也是 6,7,8 的最小值,所以還要去重,也許 id 不按序排列,再排序 id,最終得到答案
SELECT distinct a.*
FROM stadium as a,stadium as b,stadium as c
where ((a.id = b.id-1 and b.id+1 = c.id) or
(a.id-1 = b.id and a.id+1 = c.id) or
(a.id-1 = c.id and c.id-1 = b.id))
and (a.people>=100 and b.people>=100 and c.people>=100)
order by a.id;