diff --git "a/docs/notes/Leetcode-Database \351\242\230\350\247\243.md" "b/docs/notes/Leetcode-Database \351\242\230\350\247\243.md" index 07010e22de..ec1e31af8d 100644 --- "a/docs/notes/Leetcode-Database \351\242\230\350\247\243.md" +++ "b/docs/notes/Leetcode-Database \351\242\230\350\247\243.md" @@ -585,7 +585,10 @@ SELECT FROM Customers WHERE - Id NOT IN ( SELECT CustomerId FROM Orders ); + Id NOT IN ( + SELECT CustomerId + FROM Orders + ); ``` ## SQL Schema @@ -666,7 +669,9 @@ SELECT FROM Employee E, Department D, - ( SELECT DepartmentId, MAX( Salary ) Salary FROM Employee GROUP BY DepartmentId ) M + ( SELECT DepartmentId, MAX( Salary ) Salary + FROM Employee + GROUP BY DepartmentId ) M WHERE E.DepartmentId = D.Id AND E.DepartmentId = M.DepartmentId @@ -727,7 +732,10 @@ https://leetcode.com/problems/second-highest-salary/description/ ```sql SELECT - ( SELECT DISTINCT Salary FROM Employee ORDER BY Salary DESC LIMIT 1, 1 ) SecondHighestSalary; + ( SELECT DISTINCT Salary + FROM Employee + ORDER BY Salary DESC + LIMIT 1, 1 ) SecondHighestSalary; ``` ## SQL Schema @@ -756,7 +764,14 @@ VALUES CREATE FUNCTION getNthHighestSalary ( N INT ) RETURNS INT BEGIN SET N = N - 1; -RETURN ( SELECT ( SELECT DISTINCT Salary FROM Employee ORDER BY Salary DESC LIMIT N, 1 ) ); +RETURN ( + SELECT ( + SELECT DISTINCT Salary + FROM Employee + ORDER BY Salary DESC + LIMIT N, 1 + ) +); END ``` @@ -804,38 +819,93 @@ https://leetcode.com/problems/rank-scores/description/ ## Solution -要统计某个 score 的排名,只要统计大于该 score 的 score 数量,然后加 1。 +要统计某个 score 的排名,只要统计大于等于该 score 的 score 数量。 -| score | 大于该 score 的 score 数量 | 排名 | -| :---: | :---: | :---: | -| 4.1 | 2 | 3 | -| 4.2 | 1 | 2 | -| 4.3 | 0 | 1 | +| Id | score | 大于等于该 score 的 score 数量 | 排名 | +| :---: | :---: | :---: | :---: | +| 1 | 4.1 | 3 | 3 | +| 2 | 4.2 | 2 | 2 | +| 3 | 4.3 | 1 | 1 | -但是在本题中,相同的 score 只算一个排名: +使用连接操作找到某个 score 对应的大于其值的记录: -| score | 排名 | -| :---: | :---: | -| 4.1 | 3 | -| 4.1 | 3 | -| 4.2 | 2 | -| 4.2 | 2 | -| 4.3 | 1 | -| 4.3 | 1 | +```sql +SELECT + * +FROM + Scores S1 + INNER JOIN Scores S2 + ON S1.score <= S2.score +ORDER BY + S1.score DESC, S1.Id; +``` -可以按 score 进行分组,将同一个分组中的 score 只当成一个。 +| S1.Id | S1.score | S2.Id | S2.score | +| :---: | :---: | :---: | :---: | +|3| 4.3| 3 |4.3| +|2| 4.2| 2| 4.2| +|2| 4.2 |3 |4.3| +|1| 4.1 |1| 4.1| +|1| 4.1 |2| 4.2| +|1| 4.1 |3| 4.3| -但是如果分组字段只有 score 的话,那么相同的 score 最后的结果只会有一个,例如上面的 6 个记录最后只取出 3 个。 +可以看到每个 S1.score 都有对应好几条记录,我们再进行分组,并统计每个分组的数量作为 'Rank' -| score | 排名 | +```sql +SELECT + S1.score 'Score', + COUNT(*) 'Rank' +FROM + Scores S1 + INNER JOIN Scores S2 + ON S1.score <= S2.score +GROUP BY + S1.id, S1.score +ORDER BY + S1.score DESC, S1.Id; +``` + +| score | Rank | | :---: | :---: | -| 4.1 | 3 | -| 4.2 | 2 | | 4.3 | 1 | +| 4.2 | 2 | +| 4.1 | 3 | -所以在分组中需要加入 Id,每个记录显示一个结果。综上,需要使用 score 和 id 两个分组字段。 +上面的解法看似没问题,但是对于以下数据,它却得到了错误的结果: -在下面的实现中,首先将 Scores 表根据 score 字段进行自连接,得到一个新表,然后在新表上对 id 和 score 进行分组。 +| Id | score | +| :---: | :---: | +| 1 | 4.1 | +| 2 | 4.2 | +| 3 | 4.2 | + +| score | Rank | +| :---: | :--: | +| 4.2 | 2 | +| 4.2 | 2 | +| 4.1 | 3 | + +而我们希望的结果为: + +| score | Rank | +| :---: | :--: | +| 4.2 | 1 | +| 4.2 | 2 | +| 4.1 | 2 | + +连接情况如下: + +| S1.Id | S1.score | S2.Id | S2.score | +| :---: | :------: | :---: | :------: | +| 2 | 4.2 | 3 | 4.2 | +| 2 | 4.2 | 2 | 4.2 | +| 3 | 4.2 | 3 | 4.2 | +| 3 | 4.2 | 2 | 4.1 | +| 1 | 4.1 | 3 | 4.2 | +| 1 | 4.1 | 2 | 4.3 | +| 1 | 4.1 | 1 | 4.1 | + +我们想要的结果是,把分数相同的放在同一个排名,并且相同分数只占一个位置,例如上面的分数,Id=2 和 Id=3 的记录都有相同的分数,并且最高,他们并列第一。而 Id=1 的记录应该排第二名,而不是第三名。所以在进行 COUNT 计数统计时,我们需要使用 COUNT( DISTINCT S2.score ) 从而只统计一次相同的分数。 ```sql SELECT @@ -860,12 +930,12 @@ IF CREATE TABLE Scores ( Id INT, Score DECIMAL ( 3, 2 ) ); INSERT INTO Scores ( Id, Score ) VALUES - ( 1, 3.5 ), - ( 2, 3.65 ), - ( 3, 4.0 ), - ( 4, 3.85 ), - ( 5, 4.0 ), - ( 6, 3.65 ); + ( 1, 4.1 ), + ( 2, 4.1 ), + ( 3, 4.2 ), + ( 4, 4.2 ), + ( 5, 4.3 ), + ( 6, 4.3 ); ``` # 180. Consecutive Numbers diff --git "a/notes/Leetcode-Database \351\242\230\350\247\243.md" "b/notes/Leetcode-Database \351\242\230\350\247\243.md" index 07010e22de..ec1e31af8d 100644 --- "a/notes/Leetcode-Database \351\242\230\350\247\243.md" +++ "b/notes/Leetcode-Database \351\242\230\350\247\243.md" @@ -585,7 +585,10 @@ SELECT FROM Customers WHERE - Id NOT IN ( SELECT CustomerId FROM Orders ); + Id NOT IN ( + SELECT CustomerId + FROM Orders + ); ``` ## SQL Schema @@ -666,7 +669,9 @@ SELECT FROM Employee E, Department D, - ( SELECT DepartmentId, MAX( Salary ) Salary FROM Employee GROUP BY DepartmentId ) M + ( SELECT DepartmentId, MAX( Salary ) Salary + FROM Employee + GROUP BY DepartmentId ) M WHERE E.DepartmentId = D.Id AND E.DepartmentId = M.DepartmentId @@ -727,7 +732,10 @@ https://leetcode.com/problems/second-highest-salary/description/ ```sql SELECT - ( SELECT DISTINCT Salary FROM Employee ORDER BY Salary DESC LIMIT 1, 1 ) SecondHighestSalary; + ( SELECT DISTINCT Salary + FROM Employee + ORDER BY Salary DESC + LIMIT 1, 1 ) SecondHighestSalary; ``` ## SQL Schema @@ -756,7 +764,14 @@ VALUES CREATE FUNCTION getNthHighestSalary ( N INT ) RETURNS INT BEGIN SET N = N - 1; -RETURN ( SELECT ( SELECT DISTINCT Salary FROM Employee ORDER BY Salary DESC LIMIT N, 1 ) ); +RETURN ( + SELECT ( + SELECT DISTINCT Salary + FROM Employee + ORDER BY Salary DESC + LIMIT N, 1 + ) +); END ``` @@ -804,38 +819,93 @@ https://leetcode.com/problems/rank-scores/description/ ## Solution -要统计某个 score 的排名,只要统计大于该 score 的 score 数量,然后加 1。 +要统计某个 score 的排名,只要统计大于等于该 score 的 score 数量。 -| score | 大于该 score 的 score 数量 | 排名 | -| :---: | :---: | :---: | -| 4.1 | 2 | 3 | -| 4.2 | 1 | 2 | -| 4.3 | 0 | 1 | +| Id | score | 大于等于该 score 的 score 数量 | 排名 | +| :---: | :---: | :---: | :---: | +| 1 | 4.1 | 3 | 3 | +| 2 | 4.2 | 2 | 2 | +| 3 | 4.3 | 1 | 1 | -但是在本题中,相同的 score 只算一个排名: +使用连接操作找到某个 score 对应的大于其值的记录: -| score | 排名 | -| :---: | :---: | -| 4.1 | 3 | -| 4.1 | 3 | -| 4.2 | 2 | -| 4.2 | 2 | -| 4.3 | 1 | -| 4.3 | 1 | +```sql +SELECT + * +FROM + Scores S1 + INNER JOIN Scores S2 + ON S1.score <= S2.score +ORDER BY + S1.score DESC, S1.Id; +``` -可以按 score 进行分组,将同一个分组中的 score 只当成一个。 +| S1.Id | S1.score | S2.Id | S2.score | +| :---: | :---: | :---: | :---: | +|3| 4.3| 3 |4.3| +|2| 4.2| 2| 4.2| +|2| 4.2 |3 |4.3| +|1| 4.1 |1| 4.1| +|1| 4.1 |2| 4.2| +|1| 4.1 |3| 4.3| -但是如果分组字段只有 score 的话,那么相同的 score 最后的结果只会有一个,例如上面的 6 个记录最后只取出 3 个。 +可以看到每个 S1.score 都有对应好几条记录,我们再进行分组,并统计每个分组的数量作为 'Rank' -| score | 排名 | +```sql +SELECT + S1.score 'Score', + COUNT(*) 'Rank' +FROM + Scores S1 + INNER JOIN Scores S2 + ON S1.score <= S2.score +GROUP BY + S1.id, S1.score +ORDER BY + S1.score DESC, S1.Id; +``` + +| score | Rank | | :---: | :---: | -| 4.1 | 3 | -| 4.2 | 2 | | 4.3 | 1 | +| 4.2 | 2 | +| 4.1 | 3 | -所以在分组中需要加入 Id,每个记录显示一个结果。综上,需要使用 score 和 id 两个分组字段。 +上面的解法看似没问题,但是对于以下数据,它却得到了错误的结果: -在下面的实现中,首先将 Scores 表根据 score 字段进行自连接,得到一个新表,然后在新表上对 id 和 score 进行分组。 +| Id | score | +| :---: | :---: | +| 1 | 4.1 | +| 2 | 4.2 | +| 3 | 4.2 | + +| score | Rank | +| :---: | :--: | +| 4.2 | 2 | +| 4.2 | 2 | +| 4.1 | 3 | + +而我们希望的结果为: + +| score | Rank | +| :---: | :--: | +| 4.2 | 1 | +| 4.2 | 2 | +| 4.1 | 2 | + +连接情况如下: + +| S1.Id | S1.score | S2.Id | S2.score | +| :---: | :------: | :---: | :------: | +| 2 | 4.2 | 3 | 4.2 | +| 2 | 4.2 | 2 | 4.2 | +| 3 | 4.2 | 3 | 4.2 | +| 3 | 4.2 | 2 | 4.1 | +| 1 | 4.1 | 3 | 4.2 | +| 1 | 4.1 | 2 | 4.3 | +| 1 | 4.1 | 1 | 4.1 | + +我们想要的结果是,把分数相同的放在同一个排名,并且相同分数只占一个位置,例如上面的分数,Id=2 和 Id=3 的记录都有相同的分数,并且最高,他们并列第一。而 Id=1 的记录应该排第二名,而不是第三名。所以在进行 COUNT 计数统计时,我们需要使用 COUNT( DISTINCT S2.score ) 从而只统计一次相同的分数。 ```sql SELECT @@ -860,12 +930,12 @@ IF CREATE TABLE Scores ( Id INT, Score DECIMAL ( 3, 2 ) ); INSERT INTO Scores ( Id, Score ) VALUES - ( 1, 3.5 ), - ( 2, 3.65 ), - ( 3, 4.0 ), - ( 4, 3.85 ), - ( 5, 4.0 ), - ( 6, 3.65 ); + ( 1, 4.1 ), + ( 2, 4.1 ), + ( 3, 4.2 ), + ( 4, 4.2 ), + ( 5, 4.3 ), + ( 6, 4.3 ); ``` # 180. Consecutive Numbers