DW集訓營數據庫Mysql梳理[六]
1 行程和用戶(難度:困難)
項目十:行程和用戶(難度:困難)
Trips 表中存所有出租車的行程信息。每段行程有唯一鍵 Id,Client_Id 和 Driver_Id 是 Users 表中 Users_Id 的外鍵。Status 是枚舉類型,枚舉成員爲 (‘completed’, ‘cancelled_by_driver’, ‘cancelled_by_client’)。
+----+-----------+-----------+---------+--------------------+----------+
| Id | Client_Id | Driver_Id | City_Id | Status |Request_at|
+----+-----------+-----------+---------+--------------------+----------+
| 1 | 1 | 10 | 1 | completed |2013-10-01|
| 2 | 2 | 11 | 1 | cancelled_by_driver|2013-10-01|
| 3 | 3 | 12 | 6 | completed |2013-10-01|
| 4 | 4 | 13 | 6 | cancelled_by_client|2013-10-01|
| 5 | 1 | 10 | 1 | completed |2013-10-02|
| 6 | 2 | 11 | 6 | completed |2013-10-02|
| 7 | 3 | 12 | 6 | completed |2013-10-02|
| 8 | 2 | 12 | 12 | completed |2013-10-03|
| 9 | 3 | 10 | 12 | completed |2013-10-03|
| 10 | 4 | 13 | 12 | cancelled_by_driver|2013-10-03|
+----+-----------+-----------+---------+--------------------+----------+
Users 表存所有用戶。每個用戶有唯一鍵 Users_Id。Banned 表示這個用戶是否被禁止,Role 則是一個表示(‘client’, ‘driver’, ‘partner’)的枚舉類型。
+----------+--------+--------+
| Users_Id | Banned | Role |
+----------+--------+--------+
| 1 | No | client |
| 2 | Yes | client |
| 3 | No | client |
| 4 | No | client |
| 10 | No | driver |
| 11 | No | driver |
| 12 | No | driver |
| 13 | No | driver |
+----------+--------+--------+
寫一段 SQL 語句查出 2013年10月1日 至 2013年10月3日 期間非禁止用戶的取消率。基於上表,你的 SQL 語句應返回如下結果,取消率(Cancellation Rate)保留兩位小數。
+------------+-------------------+
| Day | Cancellation Rate |
+------------+-------------------+
| 2013-10-01 | 0.33 |
| 2013-10-02 | 0.00 |
| 2013-10-03 | 0.50 |
+------------+-------------------+
2 各部門前3高工資的員工(難度:中等)
將昨天employee表清空,重新插入以下數據(其實是多插入5,6兩行):
+----+-------+--------+--------------+
| Id | Name | Salary | DepartmentId |
+----+-------+--------+--------------+
| 1 | Joe | 70000 | 1 |
| 2 | Henry | 80000 | 2 |
| 3 | Sam | 60000 | 2 |
| 4 | Max | 90000 | 1 |
| 5 | Janet | 69000 | 1 |
| 6 | Randy | 85000 | 1 |
+----+-------+--------+--------------+
編寫一個 SQL 查詢,找出每個部門工資前三高的員工。例如,根據上述給定的表格,查詢結果應返回:
+------------+----------+--------+
| Department | Employee | Salary |
+------------+----------+--------+
| IT | Max | 90000 |
| IT | Randy | 85000 |
| IT | Joe | 70000 |
| Sales | Henry | 80000 |
| Sales | Sam | 60000 |
+------------+----------+--------+
此外,請考慮實現各部門前N高工資的員工功能。
思路一:
因爲只有兩個部門,我們可以取巧分別對每個部門按工資降序排名,取前三行,然後UNION。
需要注意的是,ORDER BY 和 LIMIT本身不支持在子查詢中使用。所以需要加上括號形成獨立的幾個表而不是UNION的子查詢。
3 分數排名(難度:中等)
依然是昨天的分數表,實現排名功能,但是排名是非連續的,如下:
+-------+------+
| Score | Rank |
+-------+------+
| 4.00 | 1 |
| 4.00 | 1 |
| 3.85 | 3 |
| 3.65 | 4 |
| 3.65 | 4 |
| 3.50 | 6 |
+-------+------+
思考下之前的思路,訓練五
之前的例子是編寫一個 SQL 查詢來實現分數排名。如果兩個分數相同,則兩個分數排名(Rank)相同,之前的實現爲:
SELECT Score,
(SELECT COUNT(DISTINCT Score)
FROM score AS s2
WHERE s2.Score>=s1.Score
)
FROM score AS s1
ORDER BY Score DESC;
爲了表示出排名,當時count的是排除重複數字過後的score,因此改變時,我們首先不能再加DISTINCT,這樣如果4有兩個的話,得到的默認值兩個都爲2,因此在篩選條件上我們不能讓>=,將其變爲>,變爲>後,兩個的默認值都會變爲0,此時只要再在基礎上加一就可以,如下:
SELECT Score,
(SELECT COUNT(Score)
FROM score AS s2
WHERE s2.Score > s1.Score
)+1 AS list
FROM score AS s1
ORDER BY Score DESC;
效果爲: