分享一些常见的SQL计算面试题
代碼都是基于mysql實現,如果小伙伴們有其他的思路歡迎留言~
- 1.行列轉換
- 2.分組求top-n
- 3.連續登錄問題(包括日期可間斷和不可間斷)
- 4.找連續出現3次及以上的數字
- 4.
1.行列轉換
表tb1:
表tb2:
行轉列,也就是tb1->tb2,思路是按學生分組后組內分別求各科成績。
列轉行,tb2->tb1,思路是分別選出所有人的各科成績,將各科成績做個union all合并操作。
select姓名 as name,'語文' as course, -- 帶引號表示此處按字符串對待,而不是標識符語文 as score from tb2 union all select姓名 as name,'數學' as course, 數學 as score from tb2 union all select姓名 as name,'英語' as course, 英語 as score from tb2;2.分組求top-n
還用上面行列轉換中的那張tb1表,現在求語數英中各科最高分的學生
方式1,最簡單的直接使用開窗函數:
結果:
方式2,下面這種可能沒開窗函數那么直觀理解,實現思路其實就是從tb1表里面逐條取數據,每次統計在該記錄所屬課程的所有記錄中,比這個記錄大的所有記錄總數,如果是0,說明這條記錄就是最大的。
select* from tb1where (select count(*) from tb1 tb2 where tb2.course=tb1.course and tb2.score>tb1.score) = 0;3.連續登錄問題(包括日期可間斷和不可間斷)
假設有下面這樣的一張登錄信息表,表名login:
Q1:找出連續登錄3天及以上的用戶(日期不可間斷)
求解思路是各組內對日期排序后在后面標記一個連續遞增值,如果用戶連續登錄,那登錄日期也應該是連續遞增的,登陸日期減去這個連續遞增值得到的都是同一個固定值。
查詢結果:
Q2:找出連續登錄3天及以上的用戶(間斷不超過1天也算連續)
例如“2020-01-19”和“2020-01-21”這兩天登錄過,也算連續3天登錄。
查詢結果:
上面的查詢結果可能會出現同一個用戶出現多次的情況,因為用戶可能會在滿足連續登錄3天之后間斷一段時間,之后又滿足連續3天登錄。所以也可以在上面的結果上基于用戶的uid去個重。
為了方便理解,把上面sql查詢中的t3表結果貼在下面:
4.找連續出現3次及以上的數字
比如說下面這張表,就叫tb表吧,從中選出連續出現3次及以上的數字。這是面試中被卡過得一道題,當時沒啥好的思路,想通過變量計數類似代碼編程的方式解決,下來后總覺得不妥,因為畢竟考察的是sql嘛,但又一直想不到好的解法,直到解決了上面那個可間斷日期求連續的問題,突然發現這兩題解題思路異曲同工。
下面直接給出代碼,每個中間部分都有解釋:
查詢結果:
下面將原先那種變量計數的實現放在下面,可以了解一下:
這里補充一下mysql中=和:=的區別,因為開始在這我是有些迷糊的,導致面試中寫的sql沒有跑起來,簡要來說,:=只有賦值的意思,而=包含賦值和比較是否相等兩重意思,具體哪個意思取決于使用場景,所以會有人說當使用set @xxx=xxx為變量賦值時二者都可以,當使用select @xxx=xxx為變量賦值時必須用:=。
下面附上官方文檔地址和部分截圖:https://dev.mysql.com/doc/refman/8.0/en/assignment-operators.html#operator_assign-equal
4.
總結
以上是生活随笔為你收集整理的分享一些常见的SQL计算面试题的全部內容,希望文章能夠幫你解決所遇到的問題。