Leetcode601.体育馆的人流量(困难)

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 的增加而增加。

生成数据

CREATE TABLE IF NOT EXISTS stadium (id INT, visit_date DATE NULL, people INT);

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');
INSERT INTO stadium (id, visit_date, people) VALUES ('9', '2017-01-09', '66');

解答
先把所有超过100的选出来

SELECT *
FROM stadium AS S
WHERE S.`people` >=100;

对上表三次连接 主表连接id增1 再连接id增1

SELECT *
FROM (SELECT *
FROM stadium AS S
WHERE S.`people` >=100) tmp1
JOIN (SELECT *
FROM stadium AS S
WHERE S.`people` >=100) tmp2
ON tmp1.id = tmp2.id-1 
JOIN (SELECT *
FROM stadium AS S
WHERE S.`people` >=100) tmp3
ON tmp2.id = tmp3.id-1 

把三个表的id 去重union 就可以得到结果 但是感觉代码好繁琐啊

参考别人的方法 可以这么写
取出三列id 再和表连接选出等于这三列的记录 然后去重

SELECT DISTINCT SS.`id`, SS.`visit_date`, SS.`people`
FROM stadium AS SS
JOIN (SELECT tmp1.id AS id1, tmp2.id AS id2, tmp3.id AS id3
FROM (SELECT *
FROM stadium AS S
WHERE S.`people` >=100) tmp1
JOIN (SELECT *
FROM stadium AS S
WHERE S.`people` >=100) tmp2
ON tmp1.id = tmp2.id-1 
JOIN (SELECT *
FROM stadium AS S
WHERE S.`people` >=100) tmp3
ON tmp2.id = tmp3.id-1 
) AS a
ON SS.`id` = a.id1 OR SS.`id` = a.id2 OR SS.`id` = a.id3;

但这也太繁琐了吧 而且不方便推广到高峰为n天超过100人的情况吧

感觉还是适合用变量来做

1.先用查询算出连续不小于 100 出现的统计,记为countt(小于 100 的值为0,不小于的值在上一次的基础上加一)。

SELECT S.`id`, S.`visit_date`, S.`people`,
IF(S.`people`>=100, @countt:=@countt + 1, @countt:=0) AS countt
FROM stadium AS S, (SELECT @countt:=0) AS init

countt大于等于3的一定是可以的 可是怎么把countt为1、2且满足条件的选出来呢

2.对第1步的结果增加一个标记位flag,倒叙看countt,不小于3或上一flag为1,并且countt不等于0的,标记flag为1

解释:按id倒叙再产生一个flag 列 所有count>=3的行 flag=1 同时如果上一行flag=1 并且这一行的count不为0的 flag 也等于1

SELECT *, @flag:=IF(tmp.countt>=3 OR (@flag=1 AND tmp.countt <> 0), 1, 0) AS flag
FROM (SELECT S.`id`, S.`visit_date`, S.`people`, 
IF(S.`people`>=100, @countt:=@countt + 1, @countt:=0) AS countt
FROM stadium AS S, (SELECT @countt:=0) AS init) tmp,
(SELECT @falg:=0) AS init2
ORDER BY tmp.id DESC


感慨一下是真的牛批 倒叙想不到啊

之后把flag为1的选出来即可


SELECT tmp1.id, tmp1.`visit_date`, tmp1.`people`
FROM (
SELECT *, @flag:=IF(tmp.countt>=3 OR (@flag=1 AND tmp.countt <> 0), 1, 0) AS flag
FROM (SELECT S.`id`, S.`visit_date`, S.`people`, 
IF(S.`people`>=100, @countt:=@countt + 1, @countt:=0) AS countt
FROM stadium AS S, (SELECT @countt:=0) AS init) tmp,
(SELECT @falg:=0) AS init2
ORDER BY tmp.id DESC) tmp1
WHERE tmp1.flag = 1
ORDER BY tmp1.id;

强无敌 别的方法都不想看了。。。

等等!
还有一个定义变量的方法更加简洁

SELECT id,visit_date,people,(
    @cnt:=IF(people>99,@cnt+1,0)
) AS cnt 
FROM stadium,(SELECT @cnt:=0) AS init;

这部分与前边的一致


然后做了一个笛卡尔乘积

SELECT *
FROM stadium AS S, (SELECT id,visit_date,people,(
    @cnt:=IF(people>99,@cnt+1,0)
) AS cnt 
FROM stadium,(SELECT @cnt:=0) AS init) AS tmp

结果劝退 要是遇到大数据量不就gg了

只要取出cnt大于2的数据及前cnt-1天的数据,由于id是连续的,可以取出当前id及前cnt-1个id的数据,存在超过3天连续的情况,对取出的结果去重。

SELECT DISTINCT S.*
FROM stadium AS S, (SELECT id,visit_date,people,(
    @cnt:=IF(people>99,@cnt+1,0)
) AS cnt 
FROM stadium,(SELECT @cnt:=0) AS init) AS tmp
WHERE tmp.cnt>2 AND S.`id` BETWEEN tmp.id-tmp.cnt+1 AND tmp.id

别的方法

SELECT DISTINCT S1.*
FROM stadium AS S1,stadium AS S2,stadium AS S3
WHERE S1.people>=100 AND S2.people>=100 AND S3.people>=100 AND (
    S1.id +1 = S2.id AND S1.id+2=S3.id OR
    S1.id +1 = S2.id AND S1.id-1=S3.id OR
    S1.id -1 = S2.id AND S1.id-2=S3.id
)
ORDER BY S1.id
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,406评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,732评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,711评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,380评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,432评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,301评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,145评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,008评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,443评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,649评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,795评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,501评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,119评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,731评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,865评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,899评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,724评论 2 354