LeetCode數(shù)據(jù)庫部分的一些刷題記錄
前言
秋招季的事情暫時告一段落了,閑了這么久,是時候重新學起來了。之前把操作系統(tǒng)和計網(wǎng)簡單復習了下,趁現(xiàn)在有點閑時間,繼續(xù)補強下數(shù)據(jù)結(jié)構(gòu)、算法等基礎(chǔ)知識。
準備刷LeetCode邊練邊復習,先整點簡單的——LeetCode的數(shù)據(jù)庫篇。之前在牛客上也有一個數(shù)據(jù)庫專題,做也做了二三十道,但是時間有點久了,就不寫了。
本篇就只記錄在LeetCode上數(shù)據(jù)庫部分做題的筆記
刷題
題目都在LeetCode上:https://leetcode-cn.com/problemset/database/
SQL語言用的是mysql
175、組合兩個表 簡單
這題就是連接兩張表,查表1的FirstName,LastName和表2的City,State信息,不過要注意的是這里的題目條件,要用外連接而不能內(nèi)連接。所以直接寫左連接查詢語句。
select
p.FirstName as FirstName,
p.LastName as LastName,
a.City as City,
a.State as State
from
Person as p left join Address as a
on p.PersonId = a.PersonId
176、第二高的薪水 簡單
這題目的是查詢第二高的薪水,如果不存在則返回null。
第二高的話,排序之后直接用limit 1,1就好了,關(guān)鍵是這個不存在返回null,不存在又分為表數(shù)據(jù)不夠,比如表只有一行?;蛘吡硪环N情況,薪水全部一樣,則也不存在第二高的薪水,因此這題除了按薪水降序排序外,還需要篩掉薪水相同的記錄。可以像下面這樣寫使用group by或者用distinct + order by
select
Salary as SecondHighestSalary
from
Employee
group by Salary desc
limit 1,1
但是這樣寫的話,不存在第二高記錄的話會返回空而不是null,因此還需小小改動下。最終代碼如下
select (
select
Salary
from
Employee
group by Salary desc
limit 1,1
) as SecondHighestSalary
177、第N高的薪水 中等
這題跟上一題差不多,不過是他把第二換成了第N,包裝進一個函數(shù)里面去。不過話說回來,我這sql語句還沒寫過函數(shù)呢···。不過應(yīng)該也就增刪查改那幾樣。
create function getNthHighestSalary(N int) returns int
begin
set N=N-1;
return (
select
Salary
from
Employee
group by Salary desc
limit N,1
);
end
這里注意的是第N高,limit寫法是limit N-1,1,但是這樣寫要報語法錯誤,只能先用set把N賦值為N-1。
178、分數(shù)排名 中等
這題要把成績按分數(shù)進行排名,分數(shù)降序排列倒是好辦,但按照分數(shù)進行排名就有點繞了。之前在??蜕夏莻€專題寫過類似的題目,用到的是子查詢,時間有點久了,有點忘了,看了看評論區(qū)老哥們的評論才繞出來。2333 T-T~
細心一點,把需求拆成子需求,分而治之 233~
這題要求輸出兩列,一列是分數(shù)降序排列Score,一列是分數(shù)排名(排名可并列)Rank。
分數(shù)排列查詢語句
很簡單,order by即可
select Score from Scores order by Score desc
排名查詢語句
某個分數(shù)的排名等于有多少個大于等于它的分數(shù)的數(shù)量,用語句來寫的話就是
select count(distinct Score) from Scores where Score >= s1.Score
# s1.Score是要進行排名的分數(shù)
綜合一下,整個語句就是
select
s1.Score as Score,
(
select
count(distinct Score)
from
Scores
where Score>=s1.Score
) as Rank
from
Scores as s1
order by
s1.Score desc
180、連續(xù)出現(xiàn)的數(shù)字 中等
找出表中連續(xù)出現(xiàn)3次以上的數(shù)字,這里注意是連續(xù)出現(xiàn)3次,如果只是出現(xiàn)次數(shù)大于3次的話,用count + group by 就好了,但是這里是連續(xù)出現(xiàn),就意味著id必須要連續(xù)。
這題也是看評論看來的,看完醍醐灌頂,woc,原來這么簡單啊,自己怎么想不到,枯了 T-T
連續(xù)出現(xiàn)次數(shù)大于3次,不必去數(shù)次數(shù),利用連續(xù)這個點,3張表內(nèi)連接,用值相等、Id連續(xù)條件進行限制,如果剛好出現(xiàn)次數(shù)等于3次的話,則該數(shù)在結(jié)果中出現(xiàn)一次,如果連續(xù)出現(xiàn)次數(shù)大于3次的話,該數(shù)會在結(jié)果里出現(xiàn)n-2(n>3)次,所以再加個distinct t1.Num限制。
select
distinct t1.Num as ConsecutiveNums
from
Logs as t1,
Logs as t2,
Logs as t3
where
t1.Num = t2.Num and
t2.Num = t3.Num and
t2.Id = t1.Id+1 and
t3.Id = t2.Id+1
181、超過經(jīng)理收入的員工 簡單
這題有點??蜕蟽?nèi)味了,查詢收入超過員工所屬經(jīng)理的員工的姓名。
注意這里的條件,一是員工收入超過經(jīng)理,二是該員工是在該經(jīng)理手下。
先左連接一下,連接條件是t1.ManagerId=t2.Id,然后就好辦了,一個where條件的事情
select
t1.Name as Employee
from
Employee as t1 left join Employee as t2 on t1.ManagerId=t2.Id
where
t1.Salary > t2.Salary
182、查找重復的電子郵箱 簡單
這題也太簡單了吧,group by+having。
select
Email
from
Person
group by
Email
having count(Email)>1
183、從不訂購的客戶 簡單
這題也簡單,客戶表和訂單表,找沒有訂單的客戶名,直接用個not in美滋滋
select
t1.Name as Customers
from
Customers as t1
where
t1.Id not in (
select
CustomerId
from
Orders
)
184、部門工資最高的員工 中等
這題本來以為挺容易的,兩張表,員工表和部門表,本來以為兩個表連接一下, 按部門group by + max就好了,但是寫完之后發(fā)現(xiàn)好像差點意思,于是只能就地改改,代碼改的非常丑。
select
t2.Department as Department,
t1.Name as Employee,
t1.Salary as Salary
from
Employee as t1,
( select
t2.Name as Department,
max(t1.Salary) as Salary,
t2.Id as Id
from
Employee as t1,
Department as t2
where
t1.DepartmentId = t2.Id
group by t2.Name
) as t2
where
t1.Salary = t2.Salary and
t1.DepartmentId = t2.Id
上面代碼就是相當于是,先把每個部門的部門名和最高薪水和部門ID查出來組成一個新表,然后再和Employee表連接。感覺寫得有點太冗余了,代碼太丑了,不過畢竟也不是搞DBA的,只求結(jié)果對就行了。。。
185、部門工資前三高的所有員工 困難
這題很容易能夠?qū)懗霾煌块T的工資排名
select
t1.DepartmentId as Id,
t2.Name as Department,
t1.Salary as Salary
from
Employee as t1,
Department as t2
where
t1.DepartmentId=t2.Id
group by t2.Name,t1.Salary desc
但是如何按部門取分別的前三高這里卡了很久。
嘗試了寫函數(shù),但是好像oj執(zhí)行不了,報錯。不知道這個函數(shù)這樣寫有沒有用,oj執(zhí)行不了,也不好調(diào)試。只能貼一下了。
create function getTop3(deptId int) returns int
begin
return (
select
t1.Salary as Salary
from
Employee as t1,
Department as t2
where
t1.DepartmentId = t2.Id and
t1.DepartmentId = deptId
group by t2.Name,t1.Salary desc
limit 0,3
);
end
又嘗試了下面這樣寫法,但是得到報錯:This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
select
t2.Name as Department,
t1.Name as Employee,
t1.Salary as Salary
from
Employee as t1,
Department as t2
where
t1.DepartmentId = t2.Id and
t1.Salary in (
select
e.Salary as Salary
from
Employee as e,
Department as d
where
e.DepartmentId = d.Id and
d.Id=t1.DepartmentId
group by d.Name,e.Salary desc
limit 0,3
)
order by t2.Name,t1.Salary desc
最后看了下官方題解,它的做法是對Employee表逐行進行判斷是否符合條件,而且它的前三高判斷沒有用limit,而是轉(zhuǎn)換了一下,變成比當前工資高的人不超過三個,則為前三。
select
t2.Name as Department,
t1.Name as Employee,
t1.Salary as Salary
from
Employee as t1,
Department as t2
where
t1.DepartmentId = t2.Id and
3 > (
select
count(distinct Salary)
from
Employee
where
Salary>t1.Salary and
DepartmentId = t1.DepartmentId
)
order by t2.Name,t1.Salary desc
這一題做的有點混亂了,本來按自己的想法來說,前幾前幾這種問題,一般都是排好序之后用limit,但是好像很多題目都是兩表連接,用比較符盒count判斷,這個思路要學會轉(zhuǎn)換。還有就是看了一些別人題解,發(fā)現(xiàn)也有用自定義變量等這些方法的,姿勢還是很多的,哎,太菜了。
瞎說胡扯幾句
閑著無事刷的幾個題,本來以為leetcode那些上鎖的題是通過刷題解鎖的。。今天發(fā)現(xiàn)居然還要開會員才能解鎖。
哎,反正也這么菜,先把免費的題刷了再考慮上鎖的吧,然后今天下午知道原來leetcode上鎖題要開會員才能解鎖,想找個插件把上鎖題隱藏起來的,但是只找到一個對英文官網(wǎng)有效的插件,于是又想著能不能找到幾個Tamper腳本,找是找到了,但是好像并沒啥luan用,不過倒是又引起了我對寫TamperMonkey腳本的興趣,想去搞兩遍js然后寫個leetcode隱藏上鎖題的腳本,2333
今天只寫了10題,后面看情況再更新吧。