LeetCode刷題第一週

漂亮姐姐鎮樓

本週開始每週一更新LeetCode刷題系列,堅持每週刷一些各方面的面試題,每週一做一篇大致總結,這個系列輕鬆一點,每篇開篇都放一張好看的圖片,大家可以點個贊捧捧場哈,努力堅持一下,爭取在面試時造出自己的小火箭,然後開始安心在廠裏擰螺絲。


數據庫專題

在這裏插入圖片描述

簡單

175. 組合兩個表

題目鏈接:點擊傳送至本題

題目大意:
Person表(PersonId、FirstName、LastName)Addres表(AddressId、PersonId、City、State),要求:無論Person是否有地址信息,都要基於兩表查詢 Person的以下信息:FirstName, LastName, City, State。

解題思路:
考慮到並不是每個人都有地址信息,所以應該使用外連接(本題中是left join)。

# 175. 組合兩個表
select FirstName, LastName, City, State
from Person
left join Address
on Person.PersonId=Address.PersonId;

在這裏插入圖片描述

176. 第二高的薪水

題目鏈接:點擊傳送至本題

題目大意:
Employee表(Id,Salary),要求:查詢出該表第二高的薪水(查詢出的字段名改爲SecondHighestSalary ),如果不存在第二高的薪水,查詢返回null。

解題思路:

方法1:
先查詢一次最高工資,然後在補集中再次查詢最高工資即可;
可以這樣做是因爲sql的聚合函數max自帶查詢不到返回null的特性。

方法2:
將不同的薪資降序排序,然後使用limit函數截取第二高的工資。
但是可能不存在第二高的薪水,可能表只有一條記錄,
所以要考慮當查詢不到時返回null值,使用臨時表子查詢或ifnull函數都可以解決這個問題。

# 176. 第二高的薪水

#方法1:
select max(Salary) as SecondHighestSalary 
from Employee 
where Salary < (select max(Salary) from Employee);

#方法2:
select ifnull(
    (select distinct Salary
    from Employee
    order by Salary desc
    limit 1,1),null) as SecondHighestSalary 

在這裏插入圖片描述

181. 超過經理收入的員工

題目鏈接:點擊跳轉至本題

題目大意:
Employee表(Id,Name,Salary,ManagerId),經理也屬於員工,要求:查詢出薪水高於他們的經理的員工的姓名。

解題思路:
由於經理也是員工,所以可以通過內連接,自己連接自己,則表1爲員工,表2爲經理。查詢超過經理收入的員工,需要再加上判斷條件→表1.Salary>表2.Salary。

# 181. 超過經理收入的員工
select e1.Name as "Employee"
from Employee e1 
inner join Employee e2 
on e1.ManagerId=e2.Id
where e1.Salary>e2.Salary;

182. 查找重複的電子郵箱

題目鏈接:點擊跳轉至本題

題目大意:
Person表(Id、Email),要求查詢出Person表中所有重複的電子郵箱。

解題思路:
方法1:
使用group by對Email字段分組後,添加having篩選條件。

方法2:
使用group by和count函數計算每個Email的存在次數作爲臨時表,然後對臨時表添加篩選條件即可。

# 182. 查找重複的電子郵箱

# 方法1:
select Email
from Person
group by Email
having count(Email)>1;

# 方法2:
select Email
from(
    select Email,count(Email) num
    from Person 
    group by Email
) as table_1
where num>1;

183. 從不訂購的客戶

題目鏈接:點擊跳轉至本題

題目大意:
Customers表(Id、Name)Orders表(Id、CustomerId),要求:找出所有從不訂購任何東西的客戶。(即Customers表中Id不在Orders表的CcustomerId字段的Name)

解題思路:
查詢從不訂購的客戶,可以先將訂購過商品的客戶id查詢出來,然後使用not in查詢不在此列表中的用戶。

# 183. 從不訂購的客戶

select c.Name as 'Customers'
from Customers c
where c.id not in(select CustomerId from Orders);

196. 刪除重複的電子郵箱

題目鏈接:點擊跳轉至本題

題目大意:
Person表(Id、Email),要求刪除Person表Email字段中所有重複的數據,刪除時保留Id最小的那個數據。

解題思路:
通過Email字段將Person表與自身自連接起來,形成笛卡爾積,然後刪除Id更大的那些數據,剩下的就是重複且Id最小的數據。

# 196. 刪除重複的電子郵箱

delete p1
from(
    Person as p1
    inner join Person p2
    on p1.Email=p2.Email
) where p1.Id>p2.Id;

197. 上升的溫度

題目鏈接:點擊跳轉至本題

題目大意:
Weather表(Id、RecordDate(DATE)、Temperature),要求查找比昨天溫度高的日期的Id。

解題思路:

# 197. 上升的溫度

select w1.Id as Id
from Weather w1
inner join Weather w2
on datediff(w1.RecordDate,w2.RecordDate)=1
where w1.Temperature>w2.Temperature;

在這裏插入圖片描述

中等

177. 第N高的薪水

題目鏈接:點擊跳轉至本題

題目大意:
Employee表(Id、Salary),要求查出表中第 n 高的薪水。

解題思路:
針對Employee表的Salary字段降序排列,使用limit限定語句限定範圍爲第n條。需要注意的是limit的下標默認從0開始,需要設定局部變量解決這一問題。

# 177. 第N高的薪水
CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
  set n=N-1;
  RETURN (
    select ifnull(
    (select distinct Salary
    from Employee
    order by Salary desc
    limit n,1),null)
  );
END

178. 分數排名

題目鏈接:點擊跳轉至本題

題目大意:
Scores表(Id、Score),要求依據Score分數進行排名,如果分數相同,則分數排名相同,且名次之間無間隔。

解題思路1:
給你一個分數X,如何計算出其排名Rank? 首先將所有大於等於X的分數提取爲一個集合,然後去重剩下的個數就是X的排名Rank。

解題思路2:
使用mysql8.0之後引入的dense_rank() over()函數

# 178. 分數排名

#方式1:
select s2.Score as Score,
(select count(distinct s1.Score) from Scores s1 where s1.Score>=s2.Score) as "Rank"
from Scores s2
order by s2.Score desc;
# 方式2:
select Score, dense_rank() over (order by Score desc)  as "Rank"
from Scores;

在這裏插入圖片描述

180. 連續出現的數字

題目鏈接:點擊跳轉

題目大意:
Logs表(Id,Num),要求查出Num至少連續出現三次的數字。

解題思路:
直接使用sql92語法對Logs做兩次自連接,三張表做笛卡爾積,篩選條件是三張表的Id連續的同時Num相等。另外記得加上distinct去重。

# 180. 連續出現的數字
select distinct l1.Num as "ConsecutiveNums"
from 
    Logs as l1,
    Logs as l2,
    Logs as l3
where
    l1.Id=l2.Id-1
    and l2.Id=l3.Id-1
    and l1.Num=l2.Num
    and l2.Num=l3.Num;

184. 部門工資最高的員工

題目鏈接:點擊跳轉

題目大意:
Employee表(Id,Name,Salary,DepartmentId)Department表(Id,Name),要求查找出每個部門工資最高的員工。

解題思路:
可以先在員工表中的各個部門內查詢最高工資作爲臨時表,然後再把兩張表做內連接,方便查詢到部門名,此時需要使用IN語句來掛載之前查詢到的臨時表

# 184. 部門工資最高的員工
select d.Name Department,e.Name Employee,e.Salary Salary
from Employee e
inner join Department d
on e.DepartmentId=d.Id
where (e.DepartmentId,e.Salary) in(
    select DepartmentId,max(Salary)
    from Employee
    group by DepartmentId
);

困難

185. 部門工資前三高的所有員工

題目鏈接:點擊跳轉

題目大意:
Employee表(Id,Name,Salary,DepartmentId)Department表(Id,Name),要求查詢出每個部門前三高工資的所有員工。有相同工資的保留。

解題思路:
前三高的薪水意味着有不超過3個工資比這些值大,據此可以寫出下列sql語句。然後再連接上部門表,注意連接後的篩選條件即可。

select e1.Name as 'Employee', e1.Salary
from Employee e1
where 3 >
(
    select count(distinct e2.Salary)
    from Employee e2
    where e2.Salary > e1.Salary
);
# 185. 部門工資前三高的所有員工
select 
    d.Name "Department",e1.Name "Employee",e1.Salary "Salary"
FROM 
    Employee e1
    inner join Department d
    on e1.DepartmentId=d.Id
where 3>(
    select count(distinct e2.Salary)
    from Employee e2
    where e2.Salary>e1.Salary
    and e1.DepartmentId=e2.DepartmentId
)

262. 行程和用戶

題目鏈接:點擊跳轉

題目大意:
Trips出租車表(Id,Client_Id,Driver_Id,City_Id,Status,Request_at)Users用戶表( Users_Id,Banned,Role),要求查出 2013年10月1日 至 2013年10月3日 期間非禁止用戶的取消率,保留兩位小數。

取消率的計算方式如下:(正常用戶取消的訂單數量) / (正常用戶的訂單總數)

解題思路:
將client_id和driver_id各自關聯上users_id,同時檢測是否被禁止。在此基礎上,按照日期分組、查詢正常用戶取消的訂單數量(count(status))、正常用戶的訂單總數if(T.STATUS=‘completed’,0,1)。

# 262. 行程和用戶
select T.Request_at as "Day",round(
    sum(if(T.STATUS='completed',0,1))/count(T.STATUS),2
) as "Cancellation Rate"
from Trips as T
join Users as U1 ON (T.client_id =U1.users_id and U1.banned = 'No')
join Users as U2 ON (T.driver_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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章