前言
DB學習筆記SQL篇的第三篇終於出爐啦,這次決定從HackerRank裡面的練習題中來寫,整體來說HackerRank的問題比Leetcode單純,但是他的資料量相對而言比較大,更可以訓練透過只看題目敘述來寫,而不是透過I/O來反推要怎麼寫語法。但使用HackerRank有一些小問題,使用MySQL
來做答時,會無法使用CTE
,有時候也會無法使用Window Fuction
,而推測原因是線上的MySQL
版本較舊,MySQL
中的CTE
是後面版本才有的!!!只能自己將CTE
內的東西包起來放到Query
裡!
附上DB學習筆記系列的連結,還沒讀完的朋友可以點擊下方連結去看看喔~
🚪 DB學習筆記 — 基本概念/安裝資源
🚪 DB學習筆記 — SQL刷題001
🚪 DB學習筆記 — SQL刷題002
話不多說,我們直接進入主題!
目錄
- HackerRank — The Report⭐️⭐️
- HackerRank — Placements⭐️⭐️
- HackerRank —Symmetric Pairs ⭐️⭐️⭐️
可以透過Ctrl / Command + F 來進行搜尋,找到自己有興趣的題目去練習。
HackerRank— The Report⭐️⭐️
題目敘述:
Ketty gives Eve a task to generate a report containing three columns: Name, Grade and Mark. Ketty doesn’t want the NAMES of those students who received a grade lower than 8. The report must be in descending order by grade — i.e. higher grades are entered first. If there is more than one student with the same grade (8–10) assigned to them, order those particular students by their name alphabetically.
Finally, if the grade is lower than 8, use “NULL” as their name and list them by their grades in descending order. If there is more than one student with the same grade (1–7) assigned to them, order those particular students by their marks in ascending order.
解題思路:
這題的邏輯其實非常簡單,首先,如果Grade小於8,Name這邊就要用Null
回傳。再來要把Students
表的Marks
去跟Grades
表中的Min_Marks
及Max_Marks
去做比對,若Marks
介於兩者之間,則回傳他的Grade
。之後再依據題目需求去做排續。
📌解法一:使用IF函數
來進行Name,Null
的判斷,然後用Between
跟AND
來判斷Marks
是否在範圍內。這樣就可以解出答案了!!
SELECT IF(Grade<8,NULL,Name), Grade, Marks
FROM Students S
JOIN Grades G
WHERE S.Marks BETWEEN G.min_mark AND G.max_mark
ORDER BY Grade DESC, Name ASC, Marks ASC
📌解法二:其實跟解法一的邏輯一樣,但是用CASE WHEN
來做條件判斷。用CASE WHEN
的好處是當情情境不只是二種的時候,就可以輕鬆地做判別。
SELECT CASE WHEN Grade < 8 THEN NULL
ELSE Name END , Grade, Marks
FROM Students S
JOIN Grades G
WHERE S.Marks BETWEEN G.min_mark AND G.max_mark
ORDER BY Grade DESC, Name ASC, Marks ASC
HackerRank — Placement⭐️⭐️
題目敘述:
Write a query to output the names of those students whose best friends got offered a higher salary than them. Names must be ordered by the salary amount offered to the best friends. It is guaranteed that no two students got same salary offer.
解題思路:
首先,題目共有三個表,Students表
是學生的ID
及Name
,Packages表
則是ID
與Salary
的對應關係,Friends表
則是學生與他最好朋友
的對應。從題目敘述我們可以知道,這題必須透過Friends表
中的ID
去對應Packages表
中的Salary
找出該學生自己的薪水,同時透過Friends表
中的Friend_ID
去對應Packages表
中的Salary
,然後再篩選出來,朋友薪水比較高的人的Name
。
因此這是一個非常簡單的多重JOIN
的範例。
SELECT S.Name(, S.ID, P1.Salary, Friend_ID, P2.Salary)
#只需要取出S.Name,後面只是為了讓大家知道表格間的關係
FROM Students S
JOIN Friends F
ON S.ID = F.ID
JOIN Packages P1
ON F.ID = P1.ID
JOIN Packages P2
ON F.Friend_ID = P2.ID
WHERE P2.Salary > P1.Salary
ORDER BY P2.Salary
HackerRank —Symmetric Pairs⭐️⭐️⭐️
題目敘述:
Two pairs (X1, Y1) and (X2, Y2) are said to be symmetric pairs if X1 = Y2 and X2 = Y1.
Write a query to output all such symmetric pairs in ascending order by the value of X. List the rows such that X1 ≤ Y1.
解題思路:
題目是要找出座標平面上對稱的點,(X1,Y1) = (Y1,X1),例如(3,4),(4,3)就是對稱的點。首先,必須要對稱,我們就用兩個Fuction表去做JOIN,並且兩個表的X,Y對調然後GROUP BY(X1,Y1)即可得到所謂的對稱。
再來,必須增加幾個條件才能滿足,假如有一個點是(10,10)雖然會滿足上面的敘述,但是只出現一次,並不能稱作對稱的點,所以必須出現至少一次以上。另一個則是題目的要求,列出的點必須是X1≤ Y1,例如(2,3),(3,2)這樣的兩個點,只需顯示(2,3)。那這樣答案就呼之欲出了!
SELECT F1.X, F1.Y
FROM Functions F1
JOIN Functions F2
ON F1.X = F2.Y
AND F2.X = F1.Y
#透過兩個表格JOIN,並且X,Y對應的匹配,可以找出對稱的點
GROUP BY F1.X,F1.Y
#將X,Y GROUP起來做篩選
HAVING COUNT(f1.X)>1 or f1.X<f1.Y
#須滿足對稱是兩個點,按照排序X1≤Y1
ORDER BY f1.X
小結
這次的題目難度雖然沒有比較高,但HackerRank的題目他的資料量比較大,所以不適合看Output來解題,剛好可以透過只看敘述的方式來了解題目!那我們的SQL刷題003就先到這邊~第四篇很快就會出爐了!
我是尚恩,一個從商學院畢業的菜鳥工程師,有任何想從商轉換跑道的問題都可以找我聊聊,歡迎透過Linkedin@SeanChien聯絡我~
如果喜歡我的文章可以幫我鼓掌、訂閱、分享謝謝😇!