1. 程式人生 > 資料庫 >Leetcode SQL刷題 262題

Leetcode SQL刷題 262題

Leetcode SQL 刷題


題目描述

行程和使用者
寫一段 SQL 語句查出 2013年10月1日 至 2013年10月3日 期間非禁止使用者的取消率。

Trips 表中存所有計程車的行程資訊。每段行程有唯一鍵 Id,Client_Id 和 Driver_Id 是 Users 表中 Users_Id 的外來鍵。Status 是列舉型別,列舉成員為 (‘completed’, ‘cancelled_by_driver’, ‘cancelled_by_client’)。
在這裡插入圖片描述
Users 表存所有使用者。每個使用者有唯一鍵 Users_Id。Banned 表示這個使用者是否被禁止,Role 則是一個表示(‘client’, ‘driver’, ‘partner’)的列舉型別

在這裡插入圖片描述
基於上表,你的 SQL 語句應返回如下結果,取消率(Cancellation Rate)保留兩位小數。
取消率的計算方式如下:(被司機或乘客取消的非禁止使用者生成的訂單數量) / (非禁止使用者生成的訂單總數)
輸出表

一、分析思路

1.第一種方法
首先確定非禁止使用者,使用者分為兩類,司機和乘客,這兩類使用者都是滿足非禁止條件的,所以需要t 表示出行表,u1表示司機表,u2表示乘客表

SELECT *
FROM Trips AS t INNER JOIN Users AS u1 ON (t.Driver_Id=u1.Users_Id AND u1.Banned='NO')
                INNER JOIN Users AS u2 ON (t.Client_Id=u2.Users_Id AND u2.Banned='NO')

第二步對使用者進行篩選出行日期介於2013年10月1日 至 2013年10月3日
注意:比較日期,日期一定要寫成‘2013-10-01’,‘2013-10-1’這個是不對的

SELECT *
FROM Trips AS t INNER JOIN Users AS u1 ON (t.Driver_Id=u1.Users_Id AND u1.Banned='NO')
                INNER JOIN Users AS u2 ON (t.Client_Id=u2.Users_Id AND u2.Banned='NO')
WHERE  t.Request_at BETWEEN '2013-10-01' AND '2013-10-03'

第三步確定取消率
取消率的計算方式如下:(被司機或乘客取消的非禁止使用者生成的訂單數量) / (非禁止使用者生成的訂單總數)
被司機或乘客取消的非禁止使用者生成的訂單數量:
兩種方式:

SUM(IF (t.Status='completed', 0,1))
SUM(CASE WHEN t.Status='cancelled_by_client' OR  t.Status='cancelled_by_driver' THEN 1
                      ELSE 0 END )

非禁止使用者生成的訂單總數:

COUNT(Status)

取消率(Cancellation Rate)保留兩位小數:

ROUND(SUM(IF (t.Status='completed', 0,1))/COUNT(Status),2)

第四步,結合前面的內容,按照日期進行分組

SELECT t.Request_at AS Day,ROUND(IF (t.Status='completed', 0,1) )/COUNT(Status),2) AS 'Cancellation Rate'
FROM Trips AS t INNER JOIN Users AS u1 ON (t.Driver_Id=u1.Users_Id AND u1.Banned='NO')
                INNER JOIN Users AS u2 ON (t.Client_Id=u2.Users_Id AND u2.Banned='NO')
WHERE  t.Request_at BETWEEN '2013-10-01' AND '2013-10-03'
GROUP BY  t.Request_at

2.第二種方法
找出被禁止的使用者後,不再連線行程表和使用者表,直接從行程表中排除掉被被禁止使用者的行程記錄。

被禁止的使用者用子查詢:

(
	SELECT Users_id
	FROM Users
	WHERE banned = 'Yes'
) AS A

行程表中 client_id 和 driver_id 都在此子查詢結果中的行要剔除掉。

SELECT *
FROM Trips AS t
WHERE 
t.Client_Id NOT IN (
	SELECT Users_id
	FROM Users
	WHERE banned = 'Yes'
)
AND
t.Driver_Id NOT IN (
	SELECT Users_id
	FROM Users
	WHERE banned = 'Yes'
)

後面的思路與第一種方法相同

SELECT t.Request_at AS Day,ROUND(IF (t.Status='completed', 0,1) )/COUNT(Status),2) AS 'Cancellation Rate'
FROM Trips AS t
WHERE 
t.Client_Id NOT IN (
	SELECT Users_id
	FROM Users
	WHERE banned = 'Yes'
)
AND
t.Driver_Id NOT IN (
	SELECT Users_id
	FROM Users
	WHERE banned = 'Yes'
)
AND t.Request_at BETWEEN '2013-10-01' AND '2013-10-03'
GROUP BY  t.Request_at