LeetCode——數(shù)據(jù)庫(一)

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題,后面看情況再更新吧。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容