日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

【leetcodeMySQL每周一练】- 5道题带你练习mysql

發布時間:2023/12/10 数据库 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【leetcodeMySQL每周一练】- 5道题带你练习mysql 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

🎈寫在前面

🙋?♂?大家好呀,我是超夢。小伙伴們都知道,不管是在學習中還是日常工作中,幾乎天天是要跟數據庫打交道的,為了更好的操作數據庫,我們的SQL知識儲備是必不可少的。想要掌握好SQL,那少不了每天的練習與學習。接下來小夢會帶領小伙伴們開啟LeetCode-MySQL強化訓練,通過力扣真題來復習鞏固我們的SQL知識,能在以后的工作與學習中熟練使用SQL語句。小夢會在每到題后面附加上對應的知識點,方便小伙伴們查缺補漏

🙋?♂? 小伙伴們如果在學習過程中有不明白的地方,歡迎評論區留言提問,小夢定知無不言,言無不盡。


目錄

題目一:組合兩個表

題目概述

解題思路

代碼測試

知識點小結

聯表查詢之外連接

題目二:第二高的薪水

題目概述

解題思路

代碼測試

知識點小結

limit子句

ifnull函數

題目三:超過經理收入的員工

題目概述

解題思路

代碼測試

知識點小結

內連接與外連接

題目四:查找重復的電子郵箱

題目概述

解題思路

代碼測試

知識點小結

group by與having子句

題目五:從不訂購的顧客

題目概述

解題思路

代碼測試

知識點小結

內連接與外連接


題目一:組合兩個表

題目概述

?題目:

編寫一個 SQL 查詢,滿足條件:無論 person 是否有地址信息,都需要基于表1和表2兩表提供?person 的以下信息:

FirstName, LastName, City, State

LeetCode原題地址,點擊進入~

表1: Person

+-------------+---------+ | 列名 | 類型 | +-------------+---------+ | PersonId | int | | FirstName | varchar | | LastName | varchar | +-------------+---------+ PersonId 是Person表主鍵

?表2: Address

+-------------+---------+ | 列名 | 類型 | +-------------+---------+ | AddressId | int | | PersonId | int | | City | varchar | | State | varchar | +-------------+---------+ AddressId 是Address表主鍵 PersonId 是表 Person 的外鍵

解題思路

????????1. 我們先通讀一下題目,先看題目中提到的表1(person)和表2(address),從表的結構可以看出,表1(person)是人的姓名信息,表2(address)是人的地址信息

???? ?? 2. 我們都要通過Person表與AddressId表來查詢出(FirstName, LastName, City, State)這四個字段的信息。查詢結果是兩個表里的列名,所以需要多表查詢

??????? 3. 可能不是每個人都有地址信息,所以查詢出來的數據有的person就會有City,State兩個字段的信息,有的person就會沒有,對應顯示為null。考慮到有的人可能沒有地址信息,要是查詢結構要查所有人,需要保留表1(Person)里的全部數據,所以用左聯結(left join)。? ?

??????? 4. 表 Address 中的 PersonId 是表 Person 的外關鍵字,兩個表通過personId產生聯結。


代碼測試

?這里我們使用的是左外連接

select FirstName, LastName, City, State from Person left join Address on Person.PersonId = Address.PersonId; 在LeetCode上執行測試是否成功

?

?與預期結果一致,通過!

?


知識點小結

聯表查詢之外連接

? 該題目主要考察了聯表查詢外連接的相關知識點,接下來帶著小伙伴們快速回顧一下外連接的相關知識點,幫助大家學習與鞏固。

外連接分為三種:左外連接(left join),右外連接(right join),全外連接(full join)。這里我們省略了outer 這個關鍵字。

外連接的一個重要特點:至少有一方保留全集,沒有匹配行用NULL代替。

下面小夢把這三種外連接簡單說一下:

??? 1. LEFT OUTER JOIN,簡稱LEFT JOIN,左外連接(左連接)

????? 結果集保留左表的所有行,但右表只包含與左表匹配的行。右表相應的空行為NULL值。

SELECT * FROM 表1 LEFT JOIN 表2 ON 表1.xx = 表2.xx

??? 2. RIGHT OUTER JOIN,簡稱RIGHT JOIN,右外連接 (右連接)

?????? 結果集保留右表的所有行,但左表只包含與右表匹配的行。左表相應的空行為NULL值。

SELECT * FROM 表1 RIGHT JOIN 表2 ON 表1.xx = 表2.xx ?

??? 3. FULL OUTER JOIN,簡稱FULL JOIN,全外連接

?????? 會把兩個表所有的行都顯示在結果表中。

SELECT * FROM 表1 FULL JOIN 表2 ON 表1.xx = 表2.xx

?

?

題目二:第二高的薪水

題目概述

?Employee?表

Employee 表 +----+--------+ | Id | Salary | +----+--------+ | 1 | 100 | | 2 | 200 | | 3 | 300 | +----+--------+

?

  • mployee?表中第二高的薪水(Salary),如果不存在第二高的薪水,那么查詢應返回 null。
  • 例如上述?Employee?表,SQL查詢應該返回?200 作為第二高的薪水。
+---------------------+ | SecondHighestSalary | +---------------------+ | 200 | +---------------------+

👇LeetCode原題地址,點擊進入~https://leetcode-cn.com/problems/combine-two-tables/


解題思路

?方式一

  • 首先我們先寫一個select查詢語句,查出Employee表中最高的薪水。
  • select max(salary) from Employee;

    ???? 2. 然后我們把第一步的查詢語句作為一個子句,我們通過where條件,使salary小于該子句得到的最高薪水。簡單來講就是我查詢到一個小于最高的薪水的最高薪水,不就是第二高薪水嘛。

    select max(salary) from Employee where salary < (select max(salary) from Employee);

    ??? 3. 接下來我們根據題意還需要做一個null判斷,如果不存在第二高薪水,就返回null值。這里我們用到了ifnull函數(文章知識點總結部分會有對ifnull函數的講解哦~)。

    題解:

    select ifnull(( select max(salary) from Employee where salary < (select max(salary) from Employee)),null) as SecondHighestSalary;

    方式二

  • 首先我們將salary字段進行降序排序
  • 通過distinct將alary中的值去重。這里可能會有小伙伴們問了,employee表中salary沒有重復的值呀為什么要加去重操作?小夢跟小伙伴們說一下,題目表中數據量很少,當數據量大的時候我們不能保證沒有相同數據。當出現重復數據而我們沒有進行去重操作,那我們通過降序排序也無法判斷第二高的數據在哪一位置。當進行去重操作后,我們通過降序排序就能很清楚的知道第二高的數據就是排在第二位。所以為了謹慎與正確性,我們需要加上distinct
  • 通過以上去重排序操作后,我們很清楚的知道第二高的薪水就是排在第二位,再通過limit 1,1或者limit 1 offset1來查詢出第二高的薪水。(limit1,1:前面的那一個1意思是跳過一條數據,后面的1是取一個數據,意思就是跳過一個數據,從第二條數據開始取一條數據。)(limit 1 offset 1:前面那個1意思是取一個數據,后面那一個1是跳過一條數據,整個意思就是跳過一個數據,從第二條數據開始取一條數據。)
  • 接下來我們根據題意還需要做一個null判斷,如果不存在第二高薪水,就返回null值。
  • 題解:

    ##limit selectifnull((select distinct Salaryfrom Employeeorder by Salary desclimit 1,1), null) as SecondHighestSalary;## limit offset selectifnull((select distinct Salaryfrom Employeeorder by Salary desclimit 1 offset 1), null) as SecondHighestSalary;

    代碼測試

    方式一

    select ifnull(( select max(salary) from Employee where salary < (select max(salary) from Employee)),null) as SecondHighestSalary;

    ?

    ?輸出與預期結果一致,答題成功!?

    ?

    方式二

    limit

    selectifnull((select distinct Salaryfrom Employeeorder by Salary desclimit 1,1), null) as SecondHighestSalary;

    ?

    ?輸出與預期結果一致,答題成功!

    ?

    ?limit offset

    SELECTIFNULL((SELECT DISTINCT SalaryFROM EmployeeORDER BY Salary DESCLIMIT 1 OFFSET 1),NULL) AS SecondHighestSalary

    ?

    ?輸出與預期結果一致,答題成功!

    ?


    知識點小結

    limit子句

    我們來簡單回顧一下limit與limit offset的知識點,要常常溫故而知新~

  • limit n 分句表示: 讀取 n 條數據
  • limit n, m 分句表示: 跳過 n 條數據,讀取 m 條數據
  • limit n 等價于 limit 0,n
  • limit m offset n 分句表示: 跳過 n 條數據,讀取 m 條數據

  • ifnull函數

    通過今天這一題,相信小伙伴們對ifnull函數也有些認識了。

    ifnull(expression ,y)函數解釋:

    如果第一個參數的表達式 expression 為 NULL,則返回第二個參數y的值(此題中是返回null值)。

    如果第一個參數的表達式 expression 為 不為NULL,則返回第一個參數表達式expression的值。

    題目三:超過經理收入的員工

    題目概述

    ?Employee?表

    +----+-------+--------+-----------+ | Id | Name | Salary | ManagerId | +----+-------+--------+-----------+ | 1 | Joe | 70000 | 3 | | 2 | Henry | 80000 | 4 | | 3 | Sam | 60000 | NULL | | 4 | Max | 90000 | NULL | +----+-------+--------+-----------+

    題目:Employee?表包含所有員工,他們的經理也屬于員工。每個員工都有一個 Id,此外還有一列對應員工的經理的 Id。給定?Employee?表,編寫一個 SQL 查詢,該查詢可以獲取收入超過他們經理的員工的姓名。在上面的表格中,Joe 是唯一一個收入超過他的經理的員工。查詢出的結果如下所示。

    +----------+ | Employee | +----------+ | Joe | +----------+

    👇LeetCode原題地址~https://leetcode-cn.com/problems/employees-earning-more-than-their-managers/


    解題思路

    ?????首先根據題意,Employee表包含所有員工,他們的經理也屬于員工。每個員工都有一個 Id,此外還有一列對應員工的經理的 Id。那我們看到字段ManagerId就是對應員工的經理Id,由Employee表得知joe對應的經理Id是3,Henry對應的經理Id是4。經理也屬于員工,id3對應的是Sam,Id4對應的是Max,也就是說joe對應的經理是Sam,Henry對應的經理是Max。

    ??????? 因為表既有員工信息又有經理信息,所以我們需要獲取兩次信息,我們可以把Employee既看成員工表又看成經理表。題目要求我們查找出員工工資大于經理的,那我們可以通過id字段與ManagerId字段做連接,加一個員工Salary大于經理Salary條件即可。具體方法如下。

    方法一

    ????????表中存在員工與經理兩種信息,我們需要獲取兩次信息,然后使用Where語句做條件篩查,找出員工工資大于經理的數據。

    ??????? 題解1:

    SELECT staff.Name AS 'Employee' FROMEmployee AS staff,Employee AS manager WHEREstaff.ManagerId = manager.Id AND staff.Salary > manager.Salary

    方法二

    ?????????表中存在員工與經理兩種信息,我們需要獲取兩次信息,除了使用where語句外,我們還可以使用內連接,通過on語句做條件篩查來找出員工工資大于經理的數據。

    ??????? 題解2:

    SELECT staff.NAME AS 'Employee' FROM Employee AS staff JOIN Employee AS manager ON staff .ManagerId = manager.Id AND staff .Salary > manager.Salary

    代碼測試

    ?方法一

    SELECT staff.Name AS 'Employee' FROMEmployee AS staff,Employee AS manager WHEREstaff.ManagerId = manager.Id AND staff.Salary > manager.Salary

    ??與預測結果一致,成功!

    方法二

    SELECT staff.NAME AS 'Employee' FROM Employee AS staff JOIN Employee AS manager ON staff .ManagerId = manager.Id AND staff .Salary > manager.Salary

    ??與預測結果一致,成功!


    知識點小結

    內連接與外連接

    小夢用極簡單的方式帶小伙伴們過一遍內連接與外連接。

    ?表1 classa?????????????

    ?????????

    表2 classb

    1. 內連接 inner join (join 默認就是內連接)

    表1與表2的交集,用上面兩個表演示一下

    select classa.id as aid,classb.id as bid from classa inner join classb on classa.id = classb.id;

    ?查詢的結果是classa與classb的交集

    ?2. 左外連接 left join

    結果集保留左表的所有行,但右表只包含與左表匹配的行。右表相應的空行為NULL值。

    select classa.id as aid,classb.id as bid from classa left join classb on classa.id = classb.id;

    ?3. 右外連接 right join

    結果集保留右表的所有行,但左表只包含與右表匹配的行。左表相應的空行為NULL值。

    select classa.id as aid,classb.id as bid from classa right join classb on classa.id = classb.id;

    4. 全外連接 full join

    會把兩個表所有的行都顯示在結果表中。

    select classa.id as aid,classb.id as bid from classa full join classb on classa.id = classb.id;

    小伙伴們注意啦!!!

    MySQL不支持full join!!!MySQL不支持full join!!!MySQL不支持full join!!!

    重要的事情要說三遍!!!那怎么實現和full join一樣的效果呢?那就要通過使用union來實現,具體實現SQL語句如下

    select classa.id as aid,classb.id as bid from classa left join classb on classa.id = classb.id union select classa.id as aid,classb.id as bid from classa right join classb on classa.id = classb.id;

    ?

    題目四:查找重復的電子郵箱

    題目概述

    ?題目:

    編寫一個 SQL 查詢,查找?Person 表中所有重復的電子郵箱。

    Person表

    +----+---------+ | Id | Email | +----+---------+ | 1 | a@b.com | | 2 | c@d.com | | 3 | a@b.com | +----+---------+

    根據以上輸入,你的查詢應返回以下結果:

    +---------+ | Email | +---------+ | a@b.com | +---------+

    解題思路

    ??其實這道題很簡單啦,相信小伙伴們心中已經知道該怎么做了,趕緊去LeetCode揮筆寫下答案測試一番吧!!測試完可以再看看小夢與大家的思路是否一致呢,如果有多種思路,歡迎留言寫下你們的思路與解法,大家互相學習學習~

    ??????? 根據題意,要找出表中所有重復的電子郵箱,也就是Email字段對應的數據有重復的我需要查找出來。那我們可以使用count函數來獲取Email中各電子郵箱的數量,只要數量大于1就是題目中要求的。接下來,根據該思路,小夢列出一下三種解法,小伙伴們如果有其它思路,歡迎補充~

    方法1

    我們可以先查出Email和對應Email的個數,把查出的內容當作一個臨時表,在通過查該臨時表,找出Email數量大于的1的,這樣我們就查找出了題目所要求的【找出表中所有重復的電子郵箱】。

    題解:

    select Email from (select Email, count(Email) as num from Person group by Email) as temporary where num > 1;

    方法2

    我們可以通過group by對Email進行分組,然后通過having進行條件篩查,having后面可以運用聚合函數非常方便(知識點小結部分會有group by與having的簡單講解,小伙伴們記得查閱哦~)。通過聚合函數count(Email)在having后進行條件篩查,找出Email個數大于1的,這樣我們就查找出了題目所要求的【找出表中所有重復的電子郵箱】。

    題解:

    select Email from Person group by Email having count(Email) > 1;

    方法3

    第三種方法大家可以發散一下思維,如果不用count函數怎么知道重復的Email呢?怎么查呢?小夢來帶小伙伴們一起思考,首先我們可以想想,前兩種方法實質上都是通過查出Email數判斷是否大于1,大于1就是我們所要的答案,不大1就不是。那大家有沒有注意表Person雖然Email有重復的,但是id是唯一的,那我們就可以把Person表看成兩張表,一張a表和一張b表。連接兩張表,where語句后面加上a表的Email等于b表的Email和a表的id不等于b表的id。然后查詢Email做去重操作,就得到了我們想要的答案。

    題解:

    select distinct a.Email from Person a,Person b where a.Email = b.Email and a.id <> b.id;

    代碼測試

    ?方法1

    select Email from (select Email, count(Email) as num from Person group by Email) as temporary where num > 1;

    輸入題解,進行測試

    ?測試成功!

    方法2

    select Email from Person group by Email having count(Email) > 1;

    輸入題解,進行測試

    ?測試成功!

    方法3

    select distinct a.Email from Person a,Person b where a.Email = b.Email and a.id <> b.id;

    輸入題解,進行測試

    測試成功!


    知識點小結

    group by與having子句

    SQL中的數據可以按列名分組,可以搭配聚合函數一起使用,方便我們對于數據的查詢與獲取。

    例:

    SELECT count(stuname) FROM student GROUP BY student_class;

    使用GROUP BY分組語句可以與WHERE語句一起使用,當然這里有個非常重要的地方希望小伙伴們記下來,非常重要!->當一條SQL中有聚合函數,WHERE語句,GRUOP BY語句時,他們的執行順序是怎么的呢?WHERE >GROUP BY>聚合函數。?

    所以在WHERE語句執行過濾條件中我們不能使用聚合函數,使用的話就會報錯,在這我們可以使用HAVING子句執行過濾條件篩查時使用聚合函數。小伙伴們一定要記住!


    最后呢小夢再分享一下SQL查詢語句各關鍵字的執行順序,可以拿小本本記一下了,有用的很~

    【重點】SQL的執行順序:

  • 先執行FROM
  • 再執行WHERE條件過濾
  • 再執行GROUP BY分組
  • 再執行SELECT,聚集函數
  • 再執行HAVING條件過濾
  • 再執行ORDER BY 排序
  • ?

    題目五:從不訂購的顧客

    題目概述

    Customers 表:

    +----+-------+ | Id | Name | +----+-------+ | 1 | Joe | | 2 | Henry | | 3 | Sam | | 4 | Max | +----+-------+

    Orders 表:

    +----+------------+ | Id | CustomerId | +----+------------+ | 1 | 3 | | 2 | 1 | +----+------------+

    某網站包含兩個表Customers 表Orders 表。編寫一個 SQL 查詢,找出所有從不訂購任何東西的客戶

    例如給定上述表格,你的查詢應返回:

    +-----------+ | Customers | +-----------+ | Henry | | Max | +-----------+

    LeetCode原題鏈接~ 點擊進入https://leetcode-cn.com/problems/customers-who-never-order/


    解題思路

    ?根據題目,我們先看題目要求我們查什么,要查出從不訂購任何東西的顧客。根據這一點我們可以從Orders 訂單表中得知CustomerId為1和3的是訂購過東西的顧客,而2和4則沒有訂購過任何東西。再從Customers 顧客表中查id2與id4對應的顧客名字就查到了。

    方法一

    1. 根據解題思路,我們可以先寫一個子查詢查出Orders訂單表中對應的CustomerId顧客Id

    select customerid from orders;

    2. 查出顧客Id后,我們就知道誰買過東西誰從來不買東西。我們再通過NOT IN子句給顧客Id做限制,查Customers表中顧客Id不在Orders表中的就是題目所要求的。

    select customers.name as 'Customers' from customers where customers.id not in (select customerid from orders);

    LeetCode原題解析https://leetcode-cn.com/problems/customers-who-never-order/solution/cong-bu-ding-gou-de-ke-hu-by-leetcode/

    方法二

    我們通過左外鏈接,把Customers 表與Orders 表鏈接起來,我們只需要查鏈接后Orders表的數據為NULL的數據,就是從來沒有買過東西的顧客。

    select c.name as Customers from Customers c left join Orders o on c.id = o.CustomerId where o.id is null;

    代碼測試

    ?方法一

    SQL代碼

    select customers.name as 'Customers' from customers where customers.id not in (select customerid from orders);

    執行代碼,測試

    測試成功!

    方法二

    SQL代碼

    select c.name as Customers from Customers c left join Orders o on c.id = o.CustomerId where o.id is null;

    執行代碼,測試

    測試成功


    知識點小結

    內連接與外連接

    ?表1 classa?????????????

    ?????????

    表2 classb

    1. 內連接 inner join (join 默認就是內連接)

    表1與表2的交集,用上面兩個表演示一下

    select classa.id as aid,classb.id as bid from classa inner join classb on classa.id = classb.id;

    ?查詢的結果是classa與classb的交集

    ?2. 左外連接 left join

    結果集保留左表的所有行,但右表只包含與左表匹配的行。右表相應的空行為NULL值。

    select classa.id as aid,classb.id as bid from classa left join classb on classa.id = classb.id;

    ?3. 右外連接 right join

    結果集保留右表的所有行,但左表只包含與右表匹配的行。左表相應的空行為NULL值。

    select classa.id as aid,classb.id as bid from classa right join classb on classa.id = classb.id;

    4. 全外連接 full join

    會把兩個表所有的行都顯示在結果表中。

    select classa.id as aid,classb.id as bid from classa full join classb on classa.id = classb.id;

    小伙伴們注意啦!!!

    MySQL不支持full join!!!MySQL不支持full join!!!MySQL不支持full join!!!

    重要的事情要說三遍!!!那怎么實現和full join一樣的效果呢?那就要通過使用union來實現,具體實現SQL語句如下

    select classa.id as aid,classb.id as bid from classa left join classb on classa.id = classb.id union select classa.id as aid,classb.id as bid from classa right join classb on classa.id = classb.id;


    😀感謝小伙伴們支持,如果有什么疑問,歡迎留言詢問,小夢定知無不言,言無不盡!

    ?

    ?

    ?

    總結

    以上是生活随笔為你收集整理的【leetcodeMySQL每周一练】- 5道题带你练习mysql的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。