目錄
613. 直線上的最近距離🔒
https://leetcode-cn.com/problems/shortest-distance-in-a-line/
表 point 保存了一些點在 x 軸上的座標,這些座標都是整數。
寫一個查詢語句,找到這些點中最近兩個點之間的距離。
| x |
|-----|
| -1 |
| 0 |
| 2 |
最近距離顯然是 '1' ,是點 '-1' 和 '0' 之間的距離。所以輸出應該如下:
| shortest|
|---------|
| 1 |
注意:每個點都與其他點座標不同,表 table 不會有重複座標出現。
題解
一:我們知道最近的距離,必定是排序後的相鄰元素差值的絕對值的最小值。那麼🏁是如何將每一行的數據與下一行的數據進行對比。在使用 row_number() over()函數時候,over()裏頭的分組以及排序的執行晚於 where 、group by、 order by 的執行。先生成兩張臨時表a和b,均是在原表的前面添加一個id字段,a的id從1開始,b的id從2開始。
select min(abs(a.x - b.x)) shortest from
(select ROW_NUMBER() over(order by x) as id, x from point)a
left join
(select ROW_NUMBER() over(order by x) + 1 as id, x from point)b
on a.id = b.id
where b.x is not null
二:可以考慮將x中的值兩兩組合(當然不能和自己組合),這種可以用笛卡爾積來做。這種有一個缺點,我們必須排除與自身的組合,因爲不然最小值肯定是0,但是若排出和自身值相等的組合,在有重複座標,會出錯,此時最小值應該是0,但這樣做結果必然大於0。不過該題有給出注意事項,就是不會出現重複座標,故而不會出現上述情況。
select min(abs(a.x - b.x)) shortest
from
point a
left join
point b
on a.x < b.x
182. 查找重複的電子郵箱
https://leetcode-cn.com/problems/duplicate-emails/
編寫一個 SQL 查詢,查找 Person
表中所有重複的電子郵箱。
示例:
根據以上輸入,你的查詢應返回以下結果:
說明:所有電子郵箱都是小寫字母。
題解
一:group by 分組以及聚合函數的使用。當技術大於1的時候說明是重複的。
select Email from Person group by Email having count(Email) > 1
627. 交換工資
https://leetcode-cn.com/problems/swap-salary/
給定一個 salary 表,如下所示,有 m = 男性 和 f = 女性 的值。交換所有的 f 和 m 值(例如,將所有 f 值更改爲 m,反之亦然)。要求只使用一個更新(Update)語句,並且沒有中間的臨時表。
注意,您必只能寫一個 Update 語句,請不要編寫任何 Select 語句。
例如:
運行你所編寫的更新語句之後,將會得到以下表:
題解
一:case when then else的使用。如何將字段的值按條件重新賦值。
Update salary set sex = (case when sex = "f" then "m" else "f" end)
584. 尋找用戶推薦人🔒
https://leetcode-cn.com/problems/find-customer-referee/
給定表 customer
,裏面保存了所有客戶信息和他們的推薦人。
寫一個查詢語句,返回一個編號列表,列表中編號的推薦人的編號都 不是 2。對於上面的示例數據,結果爲:
題解
一:注意null的特殊處理。下面轉自官方題解,https://leetcode-cn.com/problems/find-customer-referee/solution/xun-zhao-yong-hu-tui-jian-ren-by-leetcode/。MySQL 使用三值邏輯 —— TRUE, FALSE 和 UNKNOWN。任何與 NULL 值進行的比較都會與第三種值 UNKNOWN 做比較。這個“任何值”包括 NULL 本身!這就是爲什麼 MySQL 提供 IS NULL 和 IS NOT NULL 兩種操作來對 NULL 特殊判斷。因此,在 WHERE 語句中我們需要做一個額外的條件判斷 `referee_id IS NULL'。
select name
from customer
where referee_id != 2 or referee_id is null
下面的解法同樣是錯誤的,錯誤原因同上。避免錯誤的祕訣在於使用 IS NULL 或者 IS NOT NULL 兩種操作來對 NULL 值做特殊判斷。
SELECT name FROM customer WHERE referee_id = NULL OR referee_id <> 2;
1082. 銷售分析 I🔒
https://leetcode-cn.com/problems/sales-analysis-i/
題解
一:兩張表join, 其中第二張表c拿到最大的銷售總金額(b表,拿到每個銷售的銷售總金額),a表同b表,都是拿到每個銷售的銷售總金額,用金額join,條件銷售總金額等於最大銷售總金額。
select seller_id from
(select seller_id, sum(price) sum_price
from Sales
group by seller_id
)a
left join
(select max(sum_price) max_price from
(select seller_id, sum(price) sum_price
from Sales
group by seller_id
)b)c
on sum_price = max_price
where sum_price = max_price
分步驟:拿到每個銷售的銷售總金額
select seller_id, sum(price) sum_price
from Sales
group by seller_id
在拿到每個銷售的銷售總金額後,拿到最高的銷售金額。
select max(sum_price) max_price from
(select seller_id, sum(price) sum_price
from Sales
group by seller_id
)b
二:all的使用,max和all函數起到的作用是一樣的, all和每一個進行比較(大於最大的或者小於最小的),any 則是大於任何一個都可以(大於最小的,小於最大的)
select seller_id from
Sales
group by
seller_id
having sum(price) >=
all(select sum(price) sum_price from Sales group by seller_id)
577. 員工獎金🔒
https://leetcode-cn.com/problems/employee-bonus/
題解
一:注意null值
select name, bonus
from Employee e left join Bonus b
on e.empId = b.empId
where b.empId is null or bonus < 1000
1327. 列出指定時間段內所有的下單產品🔒
https://leetcode-cn.com/problems/list-the-products-ordered-in-a-period/
寫一個 SQL 語句,要求獲取在 2020 年 2 月份下單的數量不少於 100 的產品的名字和數目。返回結果表單的順序無要求。查詢結果的格式如下:
題解
一:日期函數:提取月份month,提取年份year。
select product_name, sum(unit) unit
from
(
select o.product_id, product_name, unit
from Orders o left join Products p
on o.product_id = p.product_id
where month(order_date) = 2 and year(order_date) = 2020
)a
group by product_id, product_name
having sum(unit) >= 100
二:當作字符串處理,like,
where order_date like "2020-02%"
select product_name, sum(unit) unit
from
(
select o.product_id, product_name, unit
from Orders o left join Products p
on o.product_id = p.product_id
where order_date like "2020-02%"
)a
group by product_id, product_name
having sum(unit) >= 100
603. 連續空餘座位 🔒
https://leetcode-cn.com/problems/consecutive-available-seats/
幾個朋友來到電影院的售票處,準備預約連續空餘座位。你能利用表 cinema ,幫他們寫一個查詢語句,獲取所有空餘座位,並將它們按照 seat_id 排序後返回嗎?
對於如上樣例,你的查詢語句應該返回如下結果。
注意:seat_id 字段是一個自增的整數,free 字段是布爾類型('1' 表示空餘, '0' 表示已被佔據)。連續空餘座位的定義是大於等於 2 個連續空餘的座位。
題解
錯解:left join會存在一個情況,只要左側非空,右側即使爲空,也會返回結果,這帶來一個不方便的例如值返回一條記錄的,按理來說這不是所要求的解,但是卻不好淘汰。例如只有一個座位且是空座位,符合and的第一個條件,以及第二個條件or後面的條件。還有當最後一張💺空閒,且前面均不空,這個座位也會被返回。
select a.seat_id
from cinema a
left join cinema b
on a.seat_id + 1 = b.seat_id
where a.free = 1 and (b.free = 1 or b.free is null)
一:之前習慣了left join,left join會存在一個情況,只要左側非空,右側即使爲空,也會返回結果,這帶來一個不方便的例如值返回一條記錄的,按理來說這不是所要求的解,但是卻不好淘汰。join兩邊均非空纔會出現,這邊沒像錯解用a.seat_id + 1 = b.seat_id,這樣會出現兩次,故用distinct。
seat_id | free | seat_id | free |
---|---|---|---|
4 | 1 | 3 | 1 |
3 | 1 | 4 | 1 |
5 | 1 | 4 | 1 |
4 | 1 | 5 | 1 |
select distinct a.seat_id
from cinema a join cinema b
on abs(a.seat_id - b.seat_id) = 1
and a.free = true and b.free = true
order by a.seat_id
1407. 排名靠前的旅行者🔒
https://leetcode-cn.com/problems/top-travellers/
id 是該表單主鍵。user_id 是本次行程的用戶的 id, 而該用戶此次行程距離爲 distance。寫一段 SQL , 報告每個用戶的旅行距離。返回的結果表單, 以 travelled_distance 降序排列, 如果有兩個或者更多的用戶旅行了相同的距離, 那麼再以 name 升序排列。查詢結果格式, 如下例所示。
Elvis 和 Lee 旅行了 450 英里, Elvis 是排名靠前的旅行者, 因爲他的名字在字母表上的排序比 Lee 更小。Bob, Jonathan, Alex 和 Alice 只有一次行程, 我們只按此次行程的全部距離對他們排序。Donald 沒有任何行程, 他的旅行距離爲 0。
題解
一:case when then來進行判斷,也可以處理給空值賦默認值的問題。
select name, case
when r.user_id is null then 0
else sum(distance) end travelled_distance
from Users u
left join Rides r
on u.id = r.user_id
group by u.id
order by travelled_distance desc, name asc
二:ifnull來處理空值,當第一個參數爲null,取第二個參數的值
select name, ifnull(sum(distance), 0) travelled_distance
from Users u
left join Rides r
on u.id = r.user_id
group by u.id
order by travelled_distance desc, name asc
1211. 查詢結果的質量和佔比🔒
https://leetcode-cn.com/problems/queries-quality-and-percentage/
此表沒有主鍵,並可能有重複的行。此表包含了一些從數據庫中收集的查詢信息。“位置”(position)列的值爲 1 到 500 。“評分”(rating)列的值爲 1 到 5 。評分小於 3 的查詢被定義爲質量很差的查詢。
題解
一:純粹的sql函數
select query_name, round(sum(rating / position) / count(rating), 2) quality,
round(sum(rating < 3) / count(rating) * 100, 2) poor_query_percentage
from Queries
group by query_name