leecode 数据库题

pull/1/head
Zhang Peng 2018-11-01 19:57:06 +08:00
parent 5ac40ffb03
commit a6b23869cc
17 changed files with 270 additions and 28 deletions

View File

@ -1,3 +0,0 @@
# Leetcode 数据库篇题解
> [题库地址](https://leetcode-cn.com/problemset/database/)

View File

@ -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)

View File

@ -1,3 +1,5 @@
-- 大的国家
--
-- 这里有张 World 表 -- 这里有张 World 表
-- --
-- +-----------------+------------+------------+--------------+---------------+ -- +-----------------+------------+------------+--------------+---------------+
@ -22,6 +24,7 @@
-- | Algeria | 37100000 | 2381741 | -- | Algeria | 37100000 | 2381741 |
-- +--------------+-------------+--------------+ -- +--------------+-------------+--------------+
SELECT name, population, area FROM World SELECT NAME, POPULATION, AREA
WHERE area > 3000000 OR population > 25000000; FROM World
WHERE AREA > 3000000 OR POPULATION > 25000000;

View File

@ -1,3 +1,5 @@
-- 【超过5名学生的课】
--
-- 有一个courses 表 ,有: student (学生) 和 class (课程)。 -- 有一个courses 表 ,有: student (学生) 和 class (课程)。
-- --
-- 请列出所有超过或等于5名学生的课。 -- 请列出所有超过或等于5名学生的课。
@ -27,4 +29,7 @@
-- Note: -- 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;

View File

@ -1,3 +1,5 @@
-- 组合两个表
--
-- 表1: Person -- 表1: Person
-- --
-- +-------------+---------+ -- +-------------+---------+
@ -29,5 +31,5 @@
SELECT Person.FirstName, Person.LastName, Address.City, Address.State SELECT Person.FirstName, Person.LastName, Address.City, Address.State
FROM Person FROM Person
LEFT JOIN Address LEFT JOIN Address
ON Person.PersonId = Address.PersonId; ON Person.PersonId = Address.PersonId;

View File

@ -1,3 +1,5 @@
-- 从不订购的客户
--
-- 某网站包含两个表Customers 表和 Orders 表。编写一个 SQL 查询,找出所有从不订购任何东西的客户。 -- 某网站包含两个表Customers 表和 Orders 表。编写一个 SQL 查询,找出所有从不订购任何东西的客户。
-- --
-- Customers 表: -- Customers 表:
@ -27,10 +29,12 @@
-- | Max | -- | Max |
-- +-----------+ -- +-----------+
SELECT Name AS Customers FROM Customers c SELECT Name AS Customers
WHERE c.Id NOT IN (SELECT DISTINCT CustomerId FROM Orders); FROM Customers c
WHERE c.Id NOT IN (SELECT DISTINCT CustomerId
FROM Orders);
SELECT Name AS Customers SELECT Name AS Customers
FROM Customers FROM Customers
INNER JOIN Orders INNER JOIN Orders
ON Customers.Id != Orders.CustomerId; ON Customers.Id != Orders.CustomerId;

View File

@ -1,3 +1,5 @@
-- 查找重复的电子邮箱
--
-- 编写一个 SQL 查询,查找 Person 表中所有重复的电子邮箱。 -- 编写一个 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;

View File

@ -1,3 +1,5 @@
-- 超过经理收入的员工
--
-- Employee 表包含所有员工,他们的经理也属于员工。每个员工都有一个 Id此外还有一列对应员工的经理的 Id。 -- Employee 表包含所有员工,他们的经理也属于员工。每个员工都有一个 Id此外还有一列对应员工的经理的 Id。
-- --
-- +----+-------+--------+-----------+ -- +----+-------+--------+-----------+
@ -21,13 +23,18 @@
-- 第 1 种查询 -- 第 1 种查询
SELECT e1.Name AS Employee SELECT e1.Name AS Employee
FROM Employee e1 FROM Employee e1
INNER JOIN Employee e2 INNER JOIN Employee e2
ON e1.ManagerId = e2.Id AND e1.Salary > e2.Salary; ON e1.ManagerId = e2.Id AND e1.Salary > e2.Salary;
-- 第 2 种解法 -- 第 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; WHERE e1.ManagerId = e2.Id AND e1.Salary > e2.Salary;
-- 第 3 种查询 -- 第 3 种查询
SELECT e1.Name AS Employee FROM Employee e1 WHERE SELECT e1.Name AS Employee
e1.Salary > (SELECT e2.Salary FROM Employee e2 WHERE e1.ManagerId = e2.Id); FROM Employee e1
WHERE
e1.Salary > (SELECT e2.Salary
FROM Employee e2
WHERE e1.ManagerId = e2.Id);

View File

@ -1,3 +1,5 @@
-- 【有趣的电影】
--
-- 某城市开了一家新的电影院,吸引了很多人过来看电影。该电影院特别注意用户体验,专门有个 LED显示板做电影推荐上面公布着影评和相关电影描述。 -- 某城市开了一家新的电影院,吸引了很多人过来看电影。该电影院特别注意用户体验,专门有个 LED显示板做电影推荐上面公布着影评和相关电影描述。
-- --
-- 作为该电影院的信息部主管,您需要编写一个 SQL查询找出所有影片描述为非 boring (不无聊) 的并且 id 为奇数 的影片,结果请按等级 rating 排列。 -- 作为该电影院的信息部主管,您需要编写一个 SQL查询找出所有影片描述为非 boring (不无聊) 的并且 id 为奇数 的影片,结果请按等级 rating 排列。
@ -24,6 +26,7 @@
-- | 1 | War | great 3D | 8.9 | -- | 1 | War | great 3D | 8.9 |
-- +---------+-----------+--------------+-----------+ -- +---------+-----------+--------------+-----------+
SELECT * FROM cinema SELECT *
WHERE description != 'boring' AND id % 2 = 1 FROM CINEMA
WHERE DESCRIPTION != 'boring' AND ID % 2 = 1
ORDER BY rating DESC; ORDER BY rating DESC;

View File

@ -1,3 +1,5 @@
-- 上升的温度
--
-- 给定一个 Weather 表,编写一个 SQL 查询,来查找与之前(昨天的)日期相比温度更高的所有日期的 Id。 -- 给定一个 Weather 表,编写一个 SQL 查询,来查找与之前(昨天的)日期相比温度更高的所有日期的 Id。
-- --
-- +---------+------------------+------------------+ -- +---------+------------------+------------------+
@ -17,6 +19,8 @@
-- | 4 | -- | 4 |
-- +----+ -- +----+
SELECT w1.Id FROM Weather w1, Weather w2 SELECT w1.Id
WHERE w1.RecordDate = DATE_ADD(w2.RecordDate,interval 1 DAY ) FROM Weather w1, Weather w2
WHERE w1.RecordDate = DATE_ADD(w2.RecordDate,interval
1 DAY )
AND w1.Temperature > w2.Temperature; AND w1.Temperature > w2.Temperature;

View File

@ -1,3 +1,5 @@
-- 第二高的薪水
--
-- 编写一个 SQL 查询,获取 Employee 表中第二高的薪水Salary -- 编写一个 SQL 查询,获取 Employee 表中第二高的薪水Salary
-- --
-- +----+--------+ -- +----+--------+
@ -15,7 +17,7 @@
-- | 200 | -- | 200 |
-- +---------------------+ -- +---------------------+
SELECT (SELECT DISTINCT SALARY
SELECT (SELECT DISTINCT salary FROM Employee FROM Employee
ORDER BY salary DESC LIMIT 1,1) ORDER BY SALARY DESC LIMIT 1,1)
AS SecondHighestSalary; AS SecondHighestSalary;

View File

@ -1,3 +1,5 @@
-- 【交换工资】
--
-- 给定一个 salary表如下所示有m=男性 和 f=女性的值 。 -- 给定一个 salary表如下所示有m=男性 和 f=女性的值 。
-- 交换所有的 f 和 m 值(例如,将所有 f 值更改为 m反之亦然)。要求使用一个更新查询,并且没有中间临时表。 -- 交换所有的 f 和 m 值(例如,将所有 f 值更改为 m反之亦然)。要求使用一个更新查询,并且没有中间临时表。
-- --
@ -18,9 +20,9 @@
-- | 3 | C | f | 5500 | -- | 3 | C | f | 5500 |
-- | 4 | D | m | 500 | -- | 4 | D | m | 500 |
UPDATE salary UPDATE SALARY
SET sex = SET SEX =
CASE sex CASE SEX
WHEN 'm' WHEN 'm'
THEN 'f' THEN 'f'
ELSE 'm' ELSE 'm'

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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

View File

@ -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;