SQL-連續記錄查詢

記錄一下一道秋招筆試SQL題目:【主要關於連續記錄查詢】

 

題目:X市建了一個新的體育館,每日人流量信息記錄在這三列的信息中,序號(id)、日期(visit_date)、人流量(people)。請編寫一個查詢語句,找到人流量的高峯期。高峯期時,至少連續三行記錄中的人流量不少於100人

例如:

對於上面的示例數據,輸出結果爲如下:

 

分析解答:【本文使用mysql】

1. 創建表格:

CREATE TABLE stadium 
(id INT auto_increment primary key not null,
visit_date date not null,
people INT not null);

 

2. 插入數據

INSERT INTO stadium VALUES
(1,"2019-01-01",10),
(2,"2019-01-02",109),
(3,"2019-01-03",150),
(4,"2019-01-04",99),
(5,"2019-01-05",146),
(6,"2019-01-06",1455),
(7,"2019-01-07",199),
(8,"2019-01-08",188);

 

3.解答思路:

(1).  題目要求輸出的時連續三行的記錄,則可以選擇三張單表進行自關聯,連接的要求即爲id序號的遞增。連接方式爲left join 

如下圖即爲無要求時的連接語句及結果:

SELECT s1.*,s2.*, s3.*
        FROM  stadium AS s1
        
        LEFT JOIN stadium AS s2
        ON s1.id+1 = s2.id
  
        LEFT JOIN stadium AS s3
        ON s1.id+2 = s3.id

有圖可知,連接的每一行的 id 時從s1 到s2遞增1, 再到s3遞增1。 

再因爲連接的每一行即爲代表連續的三行的記錄。根據題目要求,則要求people人數不小於100,即要求

這裏連接的每一行的三個people 記錄都得大於等於100。所以對上述連接結果進行一次where過濾

即加入。

(2) 過濾出連續得三行people不小於100得記錄。

SELECT s1.*,s2.*, s3.*
        FROM  stadium AS s1
        
        LEFT JOIN stadium AS s2
        ON s1.id+1 = s2.id
  
        LEFT JOIN stadium AS s3
        ON s1.id+2 = s3.id

        WHERE s1.people>=100
        AND s2.people>=100 
        AND s3.people>=100

則輸出結果爲如下圖:

此時輸出得結果即爲連接得即爲滿足條件的圖。對比原連接圖的輸出即爲

因爲是左連接,所以s1最多隻能到id=6. 後續s1的id=7.id=8不能匹配後續的s2、s3。但是輸出結果需要s1的連續內容。即需要後續的id=7,id=8的內容。所以這裏選擇把上述求取的結果作爲一個表。再連接一個原表。

(3)將上述求取結果作爲一個表。再連接一個原表

注:這裏不需要上述結果的所有內容。只需要連接後的所有id號即可。

取的上述(2)求解所有的id爲  【與上述代碼的區別只有在下代碼中 注紅的部分】

      (SELECT s1.id AS r1,s2.id AS r2, s3.id AS r3
        FROM  stadium AS s1
        
        LEFT JOIN stadium AS s2
        ON s1.id+1 = s2.id
  
        LEFT JOIN stadium AS s3
        ON s1.id+2 = s3.id
        
        WHERE s1.people>=100
        AND s2.people>=100 
        AND s3.people>=100
    )

結果爲

 

觀察,上述結果內所有出現的id都是會在連續表內出現。所以,取出所有id即可。與原表進行再連接。

連接條件即爲原表的id和上述連接表的所有id相同。

代碼如下:

SELECT s.* FROM stadium as s
 INNER JOIN 
 
   (SELECT s1.id AS r1,s2.id AS r2, s3.id AS r3
        FROM  stadium AS s1
        
        LEFT JOIN stadium AS s2
        ON s1.id+1 = s2.id
  
        LEFT JOIN stadium AS s3
        ON s1.id+2 = s3.id
        
        WHERE s1.people>=100
        AND s2.people>=100 
        AND s3.people>=100
    ) p
    WHERE (s.id = p.r1 or s.id = p.r2 or s.id = p.r3)

此時輸出結果爲

有輸出結果圖可知,id是有重複,而且順序有些亂,此時需要對輸出id進行唯一化處理(distinct)、再根據id排序。

最終的代碼:

SELECT distinct s.* FROM stadium as s
 INNER JOIN 
     (SELECT s1.id AS r1,s2.id AS r2, s3.id AS r3
        FROM  stadium AS s1
        
        LEFT JOIN stadium AS s2
        ON s1.id+1 = s2.id
  
        LEFT JOIN stadium AS s3
        ON s1.id+2 = s3.id
        
        WHERE s1.people>=100
        AND s2.people>=100 
        AND s3.people>=100
    ) p
    WHERE (s.id = p.r1 or s.id = p.r2 or s.id = p.r3)
    order by s.id; 

最終輸出結果爲:

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章