mirror of https://github.com/dunwu/db-tutorial.git
leecode 数据库题
parent
5ac40ffb03
commit
a6b23869cc
|
@ -1,3 +0,0 @@
|
|||
# Leetcode 数据库篇题解
|
||||
|
||||
> [题库地址](https://leetcode-cn.com/problemset/database/)
|
|
@ -0,0 +1,21 @@
|
|||
# Leetcode 数据库篇题解
|
||||
|
||||
> [题库地址](https://leetcode.com/problemset/database/)
|
||||
|
||||
- **难度:简单**
|
||||
- [组合两个表](easy/combine-two-tables.sql)
|
||||
- [第二高的薪水](easy/second-highest-salary.sql)
|
||||
- [超过经理收入的员工](easy/employees-earning-more-than-their-managers.sql)
|
||||
- [查找重复的电子邮箱](easy/duplicate-emails.sql)
|
||||
- [从不订购的客户](easy/customers-who-never-order.sql)
|
||||
- [上升的温度](easy/rising-temperature.sql)
|
||||
- [大的国家](easy/big-countries.sql)
|
||||
- [超过5名学生的课](easy/classes-more-than-5-students.sql)
|
||||
- [有趣的电影](easy/not-boring-movies.sql)
|
||||
- [交换工资](easy/swap-salary.sql)
|
||||
- **难度:中等**
|
||||
- [第 N 高的薪水](normal/nth-highest-salary.sql)
|
||||
- [分数排名](normal/rank-scores.sql)
|
||||
- [连续出现的数字](normal/consecutive-numbers.sql)
|
||||
- [部门工资最高的员工](normal/department-highest-salary.sql)
|
||||
- [换座位](normal/exchange-seats.sql)
|
|
@ -1,3 +1,5 @@
|
|||
-- 大的国家
|
||||
--
|
||||
-- 这里有张 World 表
|
||||
--
|
||||
-- +-----------------+------------+------------+--------------+---------------+
|
||||
|
@ -22,6 +24,7 @@
|
|||
-- | Algeria | 37100000 | 2381741 |
|
||||
-- +--------------+-------------+--------------+
|
||||
|
||||
SELECT name, population, area FROM World
|
||||
WHERE area > 3000000 OR population > 25000000;
|
||||
SELECT NAME, POPULATION, AREA
|
||||
FROM World
|
||||
WHERE AREA > 3000000 OR POPULATION > 25000000;
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
-- 【超过5名学生的课】
|
||||
--
|
||||
-- 有一个courses 表 ,有: student (学生) 和 class (课程)。
|
||||
--
|
||||
-- 请列出所有超过或等于5名学生的课。
|
||||
|
@ -27,4 +29,7 @@
|
|||
-- Note:
|
||||
-- 学生在每个课中不应被重复计算。
|
||||
|
||||
SELECT class FROM courses GROUP BY class HAVING COUNT(DISTINCT student)>4;
|
||||
SELECT CLASS
|
||||
FROM COURSES
|
||||
GROUP BY CLASS
|
||||
HAVING COUNT(DISTINCT STUDENT)>4;
|
|
@ -1,3 +1,5 @@
|
|||
-- 组合两个表
|
||||
--
|
||||
-- 表1: Person
|
||||
--
|
||||
-- +-------------+---------+
|
||||
|
@ -29,5 +31,5 @@
|
|||
|
||||
SELECT Person.FirstName, Person.LastName, Address.City, Address.State
|
||||
FROM Person
|
||||
LEFT JOIN Address
|
||||
ON Person.PersonId = Address.PersonId;
|
||||
LEFT JOIN Address
|
||||
ON Person.PersonId = Address.PersonId;
|
|
@ -1,3 +1,5 @@
|
|||
-- 从不订购的客户
|
||||
--
|
||||
-- 某网站包含两个表,Customers 表和 Orders 表。编写一个 SQL 查询,找出所有从不订购任何东西的客户。
|
||||
--
|
||||
-- Customers 表:
|
||||
|
@ -27,10 +29,12 @@
|
|||
-- | Max |
|
||||
-- +-----------+
|
||||
|
||||
SELECT Name AS Customers FROM Customers c
|
||||
WHERE c.Id NOT IN (SELECT DISTINCT CustomerId FROM Orders);
|
||||
SELECT Name AS Customers
|
||||
FROM Customers c
|
||||
WHERE c.Id NOT IN (SELECT DISTINCT CustomerId
|
||||
FROM Orders);
|
||||
|
||||
SELECT Name AS Customers
|
||||
FROM Customers
|
||||
INNER JOIN Orders
|
||||
ON Customers.Id != Orders.CustomerId;
|
||||
INNER JOIN Orders
|
||||
ON Customers.Id != Orders.CustomerId;
|
|
@ -1,3 +1,5 @@
|
|||
-- 查找重复的电子邮箱
|
||||
--
|
||||
-- 编写一个 SQL 查询,查找 Person 表中所有重复的电子邮箱。
|
||||
--
|
||||
-- 示例:
|
||||
|
@ -18,4 +20,7 @@
|
|||
-- +---------+
|
||||
-- 说明:所有电子邮箱都是小写字母。
|
||||
|
||||
SELECT Email FROM Person GROUP BY Email HAVING COUNT(*) > 1;
|
||||
SELECT Email
|
||||
FROM Person
|
||||
GROUP BY Email
|
||||
HAVING COUNT(*) > 1;
|
|
@ -1,3 +1,5 @@
|
|||
-- 超过经理收入的员工
|
||||
--
|
||||
-- Employee 表包含所有员工,他们的经理也属于员工。每个员工都有一个 Id,此外还有一列对应员工的经理的 Id。
|
||||
--
|
||||
-- +----+-------+--------+-----------+
|
||||
|
@ -21,13 +23,18 @@
|
|||
-- 第 1 种查询
|
||||
SELECT e1.Name AS Employee
|
||||
FROM Employee e1
|
||||
INNER JOIN Employee e2
|
||||
ON e1.ManagerId = e2.Id AND e1.Salary > e2.Salary;
|
||||
INNER JOIN Employee e2
|
||||
ON e1.ManagerId = e2.Id AND e1.Salary > e2.Salary;
|
||||
|
||||
-- 第 2 种解法
|
||||
SELECT e1.Name AS Employee FROM Employee e1, Employee e2
|
||||
SELECT e1.Name AS Employee
|
||||
FROM Employee e1, Employee e2
|
||||
WHERE e1.ManagerId = e2.Id AND e1.Salary > e2.Salary;
|
||||
|
||||
-- 第 3 种查询
|
||||
SELECT e1.Name AS Employee FROM Employee e1 WHERE
|
||||
e1.Salary > (SELECT e2.Salary FROM Employee e2 WHERE e1.ManagerId = e2.Id);
|
||||
SELECT e1.Name AS Employee
|
||||
FROM Employee e1
|
||||
WHERE
|
||||
e1.Salary > (SELECT e2.Salary
|
||||
FROM Employee e2
|
||||
WHERE e1.ManagerId = e2.Id);
|
|
@ -1,3 +1,5 @@
|
|||
-- 【有趣的电影】
|
||||
--
|
||||
-- 某城市开了一家新的电影院,吸引了很多人过来看电影。该电影院特别注意用户体验,专门有个 LED显示板做电影推荐,上面公布着影评和相关电影描述。
|
||||
--
|
||||
-- 作为该电影院的信息部主管,您需要编写一个 SQL查询,找出所有影片描述为非 boring (不无聊) 的并且 id 为奇数 的影片,结果请按等级 rating 排列。
|
||||
|
@ -24,6 +26,7 @@
|
|||
-- | 1 | War | great 3D | 8.9 |
|
||||
-- +---------+-----------+--------------+-----------+
|
||||
|
||||
SELECT * FROM cinema
|
||||
WHERE description != 'boring' AND id % 2 = 1
|
||||
SELECT *
|
||||
FROM CINEMA
|
||||
WHERE DESCRIPTION != 'boring' AND ID % 2 = 1
|
||||
ORDER BY rating DESC;
|
|
@ -1,3 +1,5 @@
|
|||
-- 上升的温度
|
||||
--
|
||||
-- 给定一个 Weather 表,编写一个 SQL 查询,来查找与之前(昨天的)日期相比温度更高的所有日期的 Id。
|
||||
--
|
||||
-- +---------+------------------+------------------+
|
||||
|
@ -17,6 +19,8 @@
|
|||
-- | 4 |
|
||||
-- +----+
|
||||
|
||||
SELECT w1.Id FROM Weather w1, Weather w2
|
||||
WHERE w1.RecordDate = DATE_ADD(w2.RecordDate,interval 1 DAY )
|
||||
SELECT w1.Id
|
||||
FROM Weather w1, Weather w2
|
||||
WHERE w1.RecordDate = DATE_ADD(w2.RecordDate,interval
|
||||
1 DAY )
|
||||
AND w1.Temperature > w2.Temperature;
|
|
@ -1,3 +1,5 @@
|
|||
-- 第二高的薪水
|
||||
--
|
||||
-- 编写一个 SQL 查询,获取 Employee 表中第二高的薪水(Salary) 。
|
||||
--
|
||||
-- +----+--------+
|
||||
|
@ -15,7 +17,7 @@
|
|||
-- | 200 |
|
||||
-- +---------------------+
|
||||
|
||||
|
||||
SELECT (SELECT DISTINCT salary FROM Employee
|
||||
ORDER BY salary DESC LIMIT 1,1)
|
||||
SELECT (SELECT DISTINCT SALARY
|
||||
FROM Employee
|
||||
ORDER BY SALARY DESC LIMIT 1,1)
|
||||
AS SecondHighestSalary;
|
|
@ -1,3 +1,5 @@
|
|||
-- 【交换工资】
|
||||
--
|
||||
-- 给定一个 salary表,如下所示,有m=男性 和 f=女性的值 。
|
||||
-- 交换所有的 f 和 m 值(例如,将所有 f 值更改为 m,反之亦然)。要求使用一个更新查询,并且没有中间临时表。
|
||||
--
|
||||
|
@ -18,9 +20,9 @@
|
|||
-- | 3 | C | f | 5500 |
|
||||
-- | 4 | D | m | 500 |
|
||||
|
||||
UPDATE salary
|
||||
SET sex =
|
||||
CASE sex
|
||||
UPDATE SALARY
|
||||
SET SEX =
|
||||
CASE SEX
|
||||
WHEN 'm'
|
||||
THEN 'f'
|
||||
ELSE 'm'
|
|
@ -0,0 +1,28 @@
|
|||
-- 连续出现的数字
|
||||
--
|
||||
-- 编写一个 SQL 查询,查找所有至少连续出现三次的数字。
|
||||
--
|
||||
-- +----+-----+
|
||||
-- | Id | Num |
|
||||
-- +----+-----+
|
||||
-- | 1 | 1 |
|
||||
-- | 2 | 1 |
|
||||
-- | 3 | 1 |
|
||||
-- | 4 | 2 |
|
||||
-- | 5 | 1 |
|
||||
-- | 6 | 2 |
|
||||
-- | 7 | 2 |
|
||||
-- +----+-----+
|
||||
-- 例如,给定上面的 Logs 表, 1 是唯一连续出现至少三次的数字。
|
||||
--
|
||||
-- +-----------------+
|
||||
-- | ConsecutiveNums |
|
||||
-- +-----------------+
|
||||
-- | 1 |
|
||||
-- +-----------------+
|
||||
|
||||
SELECT DISTINCT l1.num AS ConsecutiveNums
|
||||
FROM Logs l1
|
||||
JOIN Logs l2 ON l1.id=l2.id-1
|
||||
JOIN Logs l3 ON l1.id=l3.id-2
|
||||
WHERE l1.num=l2.num AND l2.num=l3.num;
|
|
@ -0,0 +1,52 @@
|
|||
-- 部门工资最高的员工
|
||||
--
|
||||
-- Employee 表包含所有员工信息,每个员工有其对应的 Id, salary 和 department Id。
|
||||
--
|
||||
-- +----+-------+--------+--------------+
|
||||
-- | Id | Name | Salary | DepartmentId |
|
||||
-- +----+-------+--------+--------------+
|
||||
-- | 1 | Joe | 70000 | 1 |
|
||||
-- | 2 | Henry | 80000 | 2 |
|
||||
-- | 3 | Sam | 60000 | 2 |
|
||||
-- | 4 | Max | 90000 | 1 |
|
||||
-- +----+-------+--------+--------------+
|
||||
-- Department 表包含公司所有部门的信息。
|
||||
--
|
||||
-- +----+----------+
|
||||
-- | Id | Name |
|
||||
-- +----+----------+
|
||||
-- | 1 | IT |
|
||||
-- | 2 | Sales |
|
||||
-- +----+----------+
|
||||
-- 编写一个 SQL 查询,找出每个部门工资最高的员工。例如,根据上述给定的表格,Max 在 IT 部门有最高工资,
|
||||
-- Henry 在 Sales 部门有最高工资。
|
||||
--
|
||||
-- +------------+----------+--------+
|
||||
-- | Department | Employee | Salary |
|
||||
-- +------------+----------+--------+
|
||||
-- | IT | Max | 90000 |
|
||||
-- | Sales | Henry | 80000 |
|
||||
-- +------------+----------+--------+
|
||||
|
||||
-- 第 1 种解法
|
||||
SELECT D.Name AS Department , E.Name AS Employee , E.Salary
|
||||
FROM
|
||||
Employee E,
|
||||
(SELECT DepartmentId, MAX(Salary) AS max
|
||||
FROM Employee
|
||||
GROUP BY DepartmentId) T,
|
||||
Department D
|
||||
WHERE E.DepartmentId = T.DepartmentId
|
||||
AND E.Salary = T.MAX
|
||||
AND E.DepartmentId = D.ID
|
||||
|
||||
-- 第 2 种解法
|
||||
SELECT D.Name AS Department , E.Name AS Employee , E.Salary
|
||||
FROM
|
||||
Employee E,
|
||||
Department D
|
||||
WHERE E.DepartmentId = D.ID
|
||||
AND (DepartmentId, Salary) IN
|
||||
(SELECT DepartmentId, MAX(Salary) AS max
|
||||
FROM Employee
|
||||
GROUP BY DepartmentId)
|
|
@ -0,0 +1,43 @@
|
|||
-- 换座位
|
||||
--
|
||||
-- 小美是一所中学的信息科技老师,她有一张 seat 座位表,平时用来储存学生名字和与他们相对应的座位 id。
|
||||
--
|
||||
-- 其中纵列的 id 是连续递增的
|
||||
--
|
||||
-- 小美想改变相邻俩学生的座位。
|
||||
--
|
||||
-- 你能不能帮她写一个 SQL query 来输出小美想要的结果呢?
|
||||
--
|
||||
-- 示例:
|
||||
--
|
||||
-- +---------+---------+
|
||||
-- | id | student |
|
||||
-- +---------+---------+
|
||||
-- | 1 | Abbot |
|
||||
-- | 2 | Doris |
|
||||
-- | 3 | Emerson |
|
||||
-- | 4 | Green |
|
||||
-- | 5 | Jeames |
|
||||
-- +---------+---------+
|
||||
-- 假如数据输入的是上表,则输出结果如下:
|
||||
--
|
||||
-- +---------+---------+
|
||||
-- | id | student |
|
||||
-- +---------+---------+
|
||||
-- | 1 | Doris |
|
||||
-- | 2 | Abbot |
|
||||
-- | 3 | Green |
|
||||
-- | 4 | Emerson |
|
||||
-- | 5 | Jeames |
|
||||
-- +---------+---------+
|
||||
-- 注意:
|
||||
--
|
||||
-- 如果学生人数是奇数,则不需要改变最后一个同学的座位。
|
||||
|
||||
SELECT
|
||||
IF (id < (SELECT COUNT(*)
|
||||
FROM seat),
|
||||
IF (id mod 2=0, id-1, id+1),
|
||||
IF (id mod 2=0, id-1, id)) AS id, student
|
||||
FROM seat
|
||||
ORDER BY id ASC;
|
|
@ -0,0 +1,30 @@
|
|||
-- 第N高的薪水
|
||||
--
|
||||
-- 编写一个 SQL 查询,获取 Employee 表中第 n 高的薪水(Salary)。
|
||||
--
|
||||
-- +----+--------+
|
||||
-- | Id | Salary |
|
||||
-- +----+--------+
|
||||
-- | 1 | 100 |
|
||||
-- | 2 | 200 |
|
||||
-- | 3 | 300 |
|
||||
-- +----+--------+
|
||||
-- 例如上述 Employee 表,n = 2 时,应返回第二高的薪水 200。如果不存在第 n 高的薪水,那么查询应返回 null。
|
||||
--
|
||||
-- +------------------------+
|
||||
-- | getNthHighestSalary(2) |
|
||||
-- +------------------------+
|
||||
-- | 200 |
|
||||
-- +------------------------+
|
||||
|
||||
CREATE FUNCTION getNthHighestSalary(N int) RETURNS INT
|
||||
BEGIN
|
||||
RETURN (
|
||||
SELECT DISTINCT Salary
|
||||
FROM Employee e
|
||||
WHERE
|
||||
N = (SELECT COUNT(DISTINCT Salary)
|
||||
FROM Employee
|
||||
WHERE Salary >= e.Salary)
|
||||
);
|
||||
END
|
|
@ -0,0 +1,34 @@
|
|||
-- 分数排名
|
||||
--
|
||||
-- 编写一个 SQL 查询来实现分数排名。如果两个分数相同,则两个分数排名(Rank)相同。
|
||||
-- 请注意,平分后的下一个名次应该是下一个连续的整数值。换句话说,名次之间不应该有“间隔”。
|
||||
--
|
||||
-- +----+-------+
|
||||
-- | Id | Score |
|
||||
-- +----+-------+
|
||||
-- | 1 | 3.50 |
|
||||
-- | 2 | 3.65 |
|
||||
-- | 3 | 4.00 |
|
||||
-- | 4 | 3.85 |
|
||||
-- | 5 | 4.00 |
|
||||
-- | 6 | 3.65 |
|
||||
-- +----+-------+
|
||||
-- 例如,根据上述给定的 Scores 表,你的查询应该返回(按分数从高到低排列):
|
||||
--
|
||||
-- +-------+------+
|
||||
-- | Score | Rank |
|
||||
-- +-------+------+
|
||||
-- | 4.00 | 1 |
|
||||
-- | 4.00 | 1 |
|
||||
-- | 3.85 | 2 |
|
||||
-- | 3.65 | 3 |
|
||||
-- | 3.65 | 3 |
|
||||
-- | 3.50 | 4 |
|
||||
-- +-------+------+
|
||||
|
||||
SELECT Score, (
|
||||
SELECT COUNT(DISTINCT score)
|
||||
FROM Scores
|
||||
WHERE score >= s.score) AS Rank
|
||||
FROM Scores s
|
||||
ORDER BY Score DESC;
|
Loading…
Reference in New Issue