一道攜程SQL筆試題

以下內容首發於我的個人博客網站:
http://riun.xyz


來自一位朋友最近做的攜程筆試題,其中有一道關於SQL的題目是這樣的:

一、題目

Mysql數據庫中有如下兩張表,app表爲應用表,儲存的是應用相關信息;alert表爲預警表,儲存的是各應用在一段時間內的預警信息。

app:

app_id app_name
1001 應用1
1002 應用2

alert:

alert_id app_id alert_info alert_date
324324 1001 預警信息1 2020-02-01 12:30:23
342343 1002 預警信息2 2020-02-01 12:31:23

請寫出查詢出前7天內預警數是Top3的應用名稱及其預警數,並按預警數由大到小排序。

原題目圖片:

在這裏插入圖片描述

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

給出的兩表數據是這樣的:
在這裏插入圖片描述
在這裏插入圖片描述

給出的最終查詢結果是這樣的:

app_id app_name alert_count
1001 application1 4
1005 application5 3
1002 application2 2

二、我的理解

最初審視這道題目的時候,讀到**”查詢出前7天內預警數是Top3”,我的想法是從最早的時間開始,向後算7天內的數據**。即,若今天是4.1號,最早的時間就是3.22號,那麼前7天內的數據應該是在3.22~3.28之間的數據。我們暫且把這個叫做思路1。

按照思路1,我開始寫sql,但最終因爲無法想出【從最早的時間開始,向後數7天】這個限制條件到底應該怎樣寫而以失敗告終。所以只寫了一個不包含此條件的sql。

我的sql是:

select app.app_id, app.app_name, res.count alert_count
from app RIGHT JOIN 
(select app_id, count(*) count from alert GROUP BY app_id order by count desc LIMIT 3) res 
on app.app_id = res.app_id

在這裏插入圖片描述

如果知道這個條件怎樣寫,那麼向裏面添加 where 時間限制條件即可。

即,最終的sql應該是:

select app.app_id, app.app_name, res.count alert_count
from app RIGHT JOIN 
(select app_id, count(*) count from alert where 時間限制條件 GROUP BY app_id order by count desc LIMIT 3) res 
on app.app_id = res.app_id

暫且先不說這個時間限制條件,也不說這個sql是否符合題意要求,來說說我的思路吧。

題目:【查詢出前7天內預警數是Top3的應用名稱及其預警數,並按預警數由大到小排序】,我的思路是如下展開的:

1、由於在alert表中每條同一臺應用的預警信息都有相同的app_id,那麼我首先想到了要在alert表裏對app_id進行分組,分組後查出各組的數量,就得到了應用與預警數的對照表。那麼sql就是:

select app_id, count(*) from alert GROUP BY app_id

(上述將count(*)換成count(qpp_id)是相同的)

查詢結果:在這裏插入圖片描述

2、然後將其按照預警數倒序排序並只拿出top3。sql就是:

select app_id, count(*) count from alert GROUP BY app_id ORDER BY count desc LIMIT 3

查詢結果:在這裏插入圖片描述

這樣只需要再拿到app_name即可。app_nameapp表裏,那麼將查詢結果作爲一個新表與app表做連接查詢即可查詢出結果。sql是:

select app.app_id, app.app_name, res.count alert_count
from app RIGHT JOIN 
(select app_id, count(*) count from alert GROUP BY app_id order by count desc LIMIT 3) res 
on app.app_id = res.app_id

查詢結果:在這裏插入圖片描述

這樣看來好像添加上 where 時間限制條件這道題目就解決了。可是後來我又重新審視了一遍題目,發現了一些問題…

三、另一個選擇

當我再次審視這道題時,我將數據仔仔細細的對照了一遍。如果按照我的思路1,即,題目中的【查詢出前7天內預警數是Top3】這樣理解:“若今天是4.1號,最早的時間就是3.22號,那麼前7天內的數據應該是在3.22~3.28之間的數據“。仔細觀察給出的數據,如果這樣算,所有數據都被包含進去了,並沒有任何一個數據因爲【前7天內】這個限制條件而被刷掉,那麼給出的查詢限制條件就沒有了意義。那麼幹嘛還要這個多餘的限制條件呢?爲了迷惑作答者的思路?爲了讓作答者寫這個”比較難寫而對本題無意義的“的時間限制條件嗎?

我覺得不是。

於是我就嘗試着換了一個我並不贊同的方式思考。假設題目中【查詢出前7天內預警數是Top3】是另一個意思:以目前爲時間點,向前數7天。比如今天是4.1,那麼前7天內的數據應該是在3.26~4.1之間的數據。 再回頭看數據, 這樣算來就存在3.22號和3.24號這兩天的數據被刷掉,那麼這個限制條件便有了意義。我們把這個叫做思路2。

現在我們不寫sql語句,我口述下數據情況(順序不代表插入順序)來判斷此思路是否正確:

  • 3.22號1003機器預警
  • 3.14號1002機器預警
  • 3.26號:
    • 1001機器預警,共4次
    • 1002機器預警,共2次
    • 1003機器預警,共1次
    • 1004機器預警,共1次
    • 1005機器預警,共3次

以上是給出的數據所表達出來的是實際情況。而題目**“請寫出查詢出前7天內預警數是Top3的應用名稱及其預警數,並按預警數由大到小排序。”** 所給出的結果是:

top3分別是:

  • 1001,4次預警
  • 1005,3次預警
  • 1002,2次預警

就說明了題目是按照思路2來的

如果按照思路1來,沒有數據被刷掉,使用了全部數據,那麼結果應該是:

top3分別是:

  • 1001,4次預警
  • 1002、1005,均3次預警
  • 1003,2次預警

顯然並不符合給出的結果。

好了,這個烏龍被發現後,我再次看我按照思路1寫的sql:就算我們找到了那個符合思路1的正確的where 時間限制條件,添加進去我們的sql仍然不對,因爲題目她並不是這個意思啊 …( _ _)ノ|。 不知道這個算不算是出題者的一個失誤:按照題目的意思明顯是思路1,但是給出的結果卻是參照思路2的。

除此之外我的sql還有一個錯誤,按照思路1來top3包含了4條數據,有一個同排名的數據。而我並沒有查出4條數據,且至今仍不知道如何將這個相同排名的全部查出來…

相同排名全部查詢】先告一段落,我們來看這道題。現在知道了她是按照思路2走,就好辦了,以當前時間點爲參照,查詢出前7天內的數據的限制語句是:

where DATE_SUB(CURDATE(), INTERVAL 6 DAY) <= date(時間字段)

我們將此字段添加到我的sql中:

select app.app_id, app.app_name, res.count alert_count
from app RIGHT JOIN 
(select app_id, count(*) count from alert where DATE_SUB(CURDATE(), INTERVAL 6 DAY) <= 
date(alert_date) GROUP BY app_id order by count desc LIMIT 3) res 
on app.app_id = res.app_id

查詢結果:在這裏插入圖片描述

和所要求的查詢結果一致。sql正確。(不過我的查詢仍不適用於存在相同排名的情況下,只適用本道題目)

希望你看的開心(●’◡’●)

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