175.組合兩個表
表1: Person
| 列名 | 類型 |
|---|---|
| PersonId | int |
| FirstName | varchar |
| LastName | varchar |
PersonId 是上表主鍵
表2: Address
| 列名 | 類型 |
|---|---|
| AddressId | int |
| PersonId | int |
| City | varchar |
| State | varchar |
AddressId 是上表主鍵
編寫一個 SQL 查詢,滿足條件:無論 person 是否有地址信息,都需要基于上述兩表提供 person 的以下信息:
| FirstName | LastName | City | State |
|---|
這道題真的非常基礎,練習兩表關聯(lián)。因為提到了無論person是否有地址,都要提供信息。所以應該是LEFT JOIN,也就是以左表為準,所有左表的行都輸出對應信息,哪怕右表無對應內容(空著)
SELECT p.FirstName, p.LastName, a.City, a.State -- 建表頭
FROM Person p LEFT JOIN Address a -- p左連接a
ON p.PersonID = a.PersonID -- 鏈接條件
?
?
?
?
?
?
?
?
?
?
176. 第二高的薪水
編寫一個 SQL 查詢,獲取 Employee 表中第二高的薪水(Salary) 。
| Id | Salary |
|---|---|
| 1 | 100 |
| 2 | 200 |
| 3 | 300 |
例如上述 Employee 表,SQL查詢應該返回 200 作為第二高的薪水。如果不存在第二高的薪水,那么查詢應返回 null。
| SecondHighestSalary |
|---|
| 200 |
不太會排序查找的寫法,參照了這篇博客《176. 第二高的薪水》
里面用了兩種方法
第一種是用where來限定,先找到最大的,用最大的做限制條件,找到小于最大的的剩余值中最大的,即為第二大的
SELECT max(e.Salary) AS SecondHighestSalary -- 找出符合條件的最大的+建表頭
FROM Employee e -- 取簡寫
WHERE e.Salary < ( -- 取出滿足小于括號內部值的部分
SELECT max(e2.Salary) FROM Employee e2 -- 括號內值為整個表最大值
)
第二種是比較正統(tǒng)的,使用limit n,m,取從第n位開始的m個值
SELECT IFNULL(( -- 如果結果為空
SELECT DISTINCT e.Salary FROM Employee e -- 此處使用了DISTINCT,因為題目求的是不相同的第二大的,而不是以人為序
ORDER BY e.Salary -- 使用工資排序
DESC limit 1,1), -- DESC降序 ASC升序
null) -- 輸出null
AS SecondHighestSalary -- 建表頭
?
?
?
?
?
?
?
?
?
?
177.第N高的薪水
編寫一個 SQL 查詢,獲取 Employee 表中第 n 高的薪水(Salary)。
| Id | Salary |
|---|---|
| 1 | 100 |
| 2 | 200 |
| 3 | 300 |
例如上述 Employee 表,n = 2 時,應返回第二高的薪水 200。如果不存在第 n 高的薪水,那么查詢應返回 null。
| getNthHighestSalary(2) |
|---|
| 200 |
這道題是176的延伸,我們可以通過 limit n-1,1來取到對應的值
但是這里存在一個問題,即n-1的值需要提前計算,并存儲在新的變量中
參考資料《177. 第N高的薪水》
-- 創(chuàng)建一個函數(shù),N作為INT型參數(shù)傳入
CREATE FUNCTION getNthHighestSalary(N INT) RETURNS INT
BEGIN
DECLARE M INT; -- 聲明一個INT型變量M
SET M = N - 1; -- 給M設值為N-1
RETURN (
# Write your MySQL query statement below.
SELECT IFNULL(( -- 設置空判斷
SELECT DISTINCT Salary -- 選取不同的Salary
FROM Employee -- 來源表
ORDER BY Salary DESC -- 排序依據(jù)
LIMIT M, 1 -- 選取M開始的1個數(shù)據(jù)
),null)
);
END
?
?
?
?
?
?
?
?
?
?
178.分數(shù)排名
編寫一個 SQL 查詢來實現(xiàn)分數(shù)排名。如果兩個分數(shù)相同,則兩個分數(shù)排名(Rank)相同。請注意,平分后的下一個名次應該是下一個連續(xù)的整數(shù)值。換句話說,名次之間不應該有“間隔”。
| Id | Score |
|---|---|
| 1 | 3.50 |
| 2 | 3.65 |
| 3 | 4.00 |
| 4 | 3.85 |
| 5 | 4.00 |
| 6 | 3.65 |
例如,根據(jù)上述給定的 Scores 表,你的查詢應該返回(按分數(shù)從高到低排列):
| Score | Rank |
|---|---|
| 4.00 | 1 |
| 4.00 | 1 |
| 3.85 | 2 |
| 3.65 | 3 |
| 3.65 | 3 |
| 3.50 | 4 |
這道題看起來沒有什么難的,引用了新的函數(shù)COUNT,計數(shù)用。還是兩個相同表,一個表用來做左側索引,另一個表使用COUNT計算,對于表1每一行,有多少個不同的值,大于等于該行的值。即為所求的Rank
但是這個題在實現(xiàn)的時候,我意外發(fā)現(xiàn)了另一個問題
首先是一段,全部使用AS做實例化標注的AC代碼
SELECT s.Score,
(
SELECT COUNT(DISTINCT s1.Score)
FROM Scores s1
WHERE s1.Score >= s.Score
) AS Rank
FROM Scores s
ORDER BY s.Score DESC
解釋起來就是:
列1:從s表取出的成績列。
列2:
????計數(shù)(s1表的Score滿足條件且不同的數(shù)量)
????????條件:s1表的Score>=s表的Score
整個表使用s表的Score逆序排序
?
然后是網上的AC代碼,參考資料《【LeetCode】178.分數(shù)排名》
select Score,
(
select count(distinct Score)
from Scores
where Score >=s.Score
) Rank
from Scores s
order by Score DESC;
與第一段代碼相似,只是內部的Score沒有起名字代表。
?
接著是我的WA代碼(輸出結果中所有的Rank均為4)
SELECT Score,
(
SELECT COUNT(DISTINCT s1.Score)
FROM Scores s1
WHERE s1.Score >= Score
) AS Rank
FROM Scores
ORDER BY Score DESC
差異在于,我是外部的Score沒有起名字代表。
差異在哪呢?詢問了銅魚(CuFish)和鎕老師(Golden Tang),他告訴我是作用域的問題。
SQL是從FROM先計算,然后反過來計算SELECT內容
使用函數(shù)調用來解釋,大致是。
首先外部調用FROM Scores,生成一個Score變量
接著SELECT內部調用Scores,生成一個新的Score變量,覆蓋了原來的Score變量。此時想調用外部的Score變量,就需要一個類似于實例化的過程,通過調用實例化對象s.Score,找到對應的Score
?
?
?
?
?
?
?
?
?
?
180.連續(xù)出現(xiàn)的數(shù)字
編寫一個 SQL 查詢,查找所有至少連續(xù)出現(xiàn)三次的數(shù)字。
| Id | Num |
|---|---|
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 2 |
| 5 | 1 |
| 6 | 2 |
| 7 | 2 |
例如,給定上面的 Logs 表, 1 是唯一連續(xù)出現(xiàn)至少三次的數(shù)字。
| ConsecutiveNums |
|---|
| 1 |
網上的方法,建了三個同樣的表,用來三個表交叉查找
參考資料《180. Consecutive Numbers(連續(xù)出現(xiàn)的數(shù)字)》
SELECT DISTINCT log1.Num AS ConsecutiveNums
-- 創(chuàng)建表頭,使用DISTINCT是因為,可能1連續(xù)出現(xiàn)4次或更多,應只輸出一次
FROM logs log1, logs log2, logs log3
-- 引用三張表
WHERE log1.Num = log2.Num -- 限定條件
AND log1.Num = log3.Num
AND log1.Id + 1 = log2.Id
AND log1.Id + 2 = log3.Id