一道携程SQL笔试题
以下內(nèi)容首發(fā)于我的個人博客網(wǎng)站:
http://riun.xyz
來自一位朋友最近做的攜程筆試題,其中有一道關(guān)于SQL的題目是這樣的:
一、題目
Mysql數(shù)據(jù)庫中有如下兩張表,app表為應(yīng)用表,儲存的是應(yīng)用相關(guān)信息;alert表為預警表,儲存的是各應(yīng)用在一段時間內(nèi)的預警信息。
app:
| 1001 | 應(yīng)用1 |
| 1002 | 應(yīng)用2 |
| … | … |
alert:
| 324324 | 1001 | 預警信息1 | 2020-02-01 12:30:23 |
| 342343 | 1002 | 預警信息2 | 2020-02-01 12:31:23 |
| … | … | … | … |
請寫出查詢出前7天內(nèi)預警數(shù)是Top3的應(yīng)用名稱及其預警數(shù),并按預警數(shù)由大到小排序。
原題目圖片:
給出的兩表數(shù)據(jù)是這樣的:
給出的最終查詢結(jié)果是這樣的:
| 1001 | application1 | 4 |
| 1005 | application5 | 3 |
| 1002 | application2 | 2 |
二、我的理解
最初審視這道題目的時候,讀到**”查詢出前7天內(nèi)預警數(shù)是Top3”,我的想法是從最早的時間開始,向后算7天內(nèi)的數(shù)據(jù)**。即,若今天是4.1號,最早的時間就是3.22號,那么前7天內(nèi)的數(shù)據(jù)應(yīng)該是在3.22~3.28之間的數(shù)據(jù)。我們暫且把這個叫做思路1。
按照思路1,我開始寫sql,但最終因為無法想出【從最早的時間開始,向后數(shù)7天】這個限制條件到底應(yīng)該怎樣寫而以失敗告終。所以只寫了一個不包含此條件的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應(yīng)該是:
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天內(nèi)預警數(shù)是Top3的應(yīng)用名稱及其預警數(shù),并按預警數(shù)由大到小排序】,我的思路是如下展開的:
1、由于在alert表中每條同一臺應(yīng)用的預警信息都有相同的app_id,那么我首先想到了要在alert表里對app_id進行分組,分組后查出各組的數(shù)量,就得到了應(yīng)用與預警數(shù)的對照表。那么sql就是:
select app_id, count(*) from alert GROUP BY app_id(上述將count(*)換成count(qpp_id)是相同的)
查詢結(jié)果:
2、然后將其按照預警數(shù)倒序排序并只拿出top3。sql就是:
select app_id, count(*) count from alert GROUP BY app_id ORDER BY count desc LIMIT 3查詢結(jié)果:
這樣只需要再拿到app_name即可。app_name在app表里,那么將查詢結(jié)果作為一個新表與app表做連接查詢即可查詢出結(jié)果。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查詢結(jié)果:
這樣看來好像添加上 where 時間限制條件這道題目就解決了。可是后來我又重新審視了一遍題目,發(fā)現(xiàn)了一些問題…
三、另一個選擇
當我再次審視這道題時,我將數(shù)據(jù)仔仔細細的對照了一遍。如果按照我的思路1,即,題目中的【查詢出前7天內(nèi)預警數(shù)是Top3】這樣理解:“若今天是4.1號,最早的時間就是3.22號,那么前7天內(nèi)的數(shù)據(jù)應(yīng)該是在3.22~3.28之間的數(shù)據(jù)“。仔細觀察給出的數(shù)據(jù),如果這樣算,所有數(shù)據(jù)都被包含進去了,并沒有任何一個數(shù)據(jù)因為【前7天內(nèi)】這個限制條件而被刷掉,那么給出的查詢限制條件就沒有了意義。那么干嘛還要這個多余的限制條件呢?為了迷惑作答者的思路?為了讓作答者寫這個”比較難寫而對本題無意義的“的時間限制條件嗎?
我覺得不是。
于是我就嘗試著換了一個我并不贊同的方式思考。假設(shè)題目中【查詢出前7天內(nèi)預警數(shù)是Top3】是另一個意思:以目前為時間點,向前數(shù)7天。比如今天是4.1,那么前7天內(nèi)的數(shù)據(jù)應(yīng)該是在3.26~4.1之間的數(shù)據(jù)。 再回頭看數(shù)據(jù), 這樣算來就存在3.22號和3.24號這兩天的數(shù)據(jù)被刷掉,那么這個限制條件便有了意義。我們把這個叫做思路2。
現(xiàn)在我們不寫sql語句,我口述下數(shù)據(jù)情況(順序不代表插入順序)來判斷此思路是否正確:
- 3.22號1003機器預警
- 3.14號1002機器預警
- 3.26號:
- 1001機器預警,共4次
- 1002機器預警,共2次
- 1003機器預警,共1次
- 1004機器預警,共1次
- 1005機器預警,共3次
以上是給出的數(shù)據(jù)所表達出來的是實際情況。而題目**“請寫出查詢出前7天內(nèi)預警數(shù)是Top3的應(yīng)用名稱及其預警數(shù),并按預警數(shù)由大到小排序。”** 所給出的結(jié)果是:
top3分別是:
- 1001,4次預警
- 1005,3次預警
- 1002,2次預警
就說明了題目是按照思路2來的。
如果按照思路1來,沒有數(shù)據(jù)被刷掉,使用了全部數(shù)據(jù),那么結(jié)果應(yīng)該是:
top3分別是:
- 1001,4次預警
- 1002、1005,均3次預警
- 1003,2次預警
顯然并不符合給出的結(jié)果。
好了,這個烏龍被發(fā)現(xiàn)后,我再次看我按照思路1寫的sql:就算我們找到了那個符合思路1的正確的where 時間限制條件,添加進去我們的sql仍然不對,因為題目她并不是這個意思啊 …( _ _)ノ|。 不知道這個算不算是出題者的一個失誤:按照題目的意思明顯是思路1,但是給出的結(jié)果卻是參照思路2的。
除此之外我的sql還有一個錯誤,按照思路1來top3包含了4條數(shù)據(jù),有一個同排名的數(shù)據(jù)。而我并沒有查出4條數(shù)據(jù),且至今仍不知道如何將這個相同排名的全部查出來…
【相同排名全部查詢】先告一段落,我們來看這道題。現(xiàn)在知道了她是按照思路2走,就好辦了,以當前時間點為參照,查詢出前7天內(nèi)的數(shù)據(jù)的限制語句是:
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查詢結(jié)果:
和所要求的查詢結(jié)果一致。sql正確。(不過我的查詢?nèi)圆贿m用于存在相同排名的情況下,只適用本道題目)
希望你看的開心(●’?’●)
總結(jié)
以上是生活随笔為你收集整理的一道携程SQL笔试题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PROFINET及其同步实时通讯分析
- 下一篇: Leetcode(11)-盛最多水的容器