├── LICENSE
├── README.md
├── 交换工资.md
├── 从不订购的客户.md
├── 分数排名.md
├── 删除重复的电子邮箱.md
├── 大的国家.md
├── 有趣的电影.md
├── 查找重复的电子邮箱.md
├── 查询01课程比02课程成绩高的学生信息和课程分数.md
├── 第N高的薪水.md
├── 第二高的薪水.md
├── 组合两个表.md
├── 超过5名学生的课.md
├── 超过经理收入的员工.md
└── 部门工资最高的员工.md
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 高永立
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
Leetcode数据库问题的解决方案
2 |
3 | LeetCode database problemset
4 |
5 |
6 | |#|题名|难度|
7 | |--|--|--|
8 | |175|[组合两个表](组合两个表.md)|简单|
9 | |176|[第二高的薪水](第二高的薪水.md)|简单|
10 | |177|[第N高的薪水](第N高的薪水.md)|中等|
11 | |178|[分数排名](分数排名.md)|中等|
12 | |181|[超过经理收入的员工](超过经理收入的员工.md)|简单|
13 | |182|[查找重复的电子邮箱](查找重复的电子邮箱.md)|简单|
14 | |183|[从不订购的客户](从不订购的客户.md)|简单|
15 | |184|[部门工资最高的员工](部门工资最高的员工.md)|中等|
16 | |196|[删除重复的电子邮箱](删除重复的电子邮箱.md)|简单|
17 | |595|[大的国家](大的国家.md)|简单|
18 | |595|[超过5名学生的课](超过5名学生的课.md)|简单|
19 | |620|[有趣的电影](有趣的电影.md)|简单|
20 | |626|[交换工资](交换工资.md)|简单|
21 |
22 |
23 |
24 | # License
25 | MIT
26 |
27 |
28 |
--------------------------------------------------------------------------------
/交换工资.md:
--------------------------------------------------------------------------------
1 | 交换工资
2 |
3 | 给定一个 salary表,如下所示,有m=男性 和 f=女性的值 。交换所有的 f 和 m 值(例如,将所有 f 值更改为 m,反之亦然)。要求使用一个更新查询,并且没有中间临时表。
4 | 表如下:
5 |
6 | | id | name | sex | salary |
7 | |----|------|-----|--------|
8 | | 1 | A | m | 2500 |
9 | | 2 | B | f | 1500 |
10 | | 3 | C | m | 5500 |
11 | | 4 | D | f | 500 |
12 |
13 | 运行你所编写的查询语句之后,将会得到以下表:
14 |
15 | | id | name | sex | salary |
16 | |----|------|-----|--------|
17 | | 1 | A | f | 2500 |
18 | | 2 | B | m | 1500 |
19 | | 3 | C | f | 5500 |
20 | | 4 | D | m | 500 |
21 |
22 | 可以在SQL语句中使用IF表达式,
23 | IF 表达式的语法 IF(expr1,expr2,expr3), 如果expr1是TRUE则IF返回 expr2,否则返回 expr3,可以返回字符串或者数字。
24 | ` update salary set sex = if (sex='m','f',m); `
25 |
--------------------------------------------------------------------------------
/从不订购的客户.md:
--------------------------------------------------------------------------------
1 | 从不订购的客户
2 |
3 | 某网站包含两个表,Customers 表和 Orders 表。编写一个 SQL 查询,找出所有从不订购任何东西的客户。
4 | Customers 表:
5 |
6 | | Id | Name |
7 | |----|-------|
8 | | 1 | Joe |
9 | | 2 | Henry |
10 | | 3 | Sam |
11 | | 4 | Max |
12 |
13 | Orders 表:
14 |
15 | | Id | CustomerId |
16 | |----|------------|
17 | | 1 | 3 |
18 | | 2 | 1 |
19 |
20 | 例如给定上述表格,你的查询应返回:
21 |
22 | | Customers |
23 | |-----------|
24 | | Henry |
25 | | Max |
26 |
27 | ```
28 | select c.name as Customers from Customers as c where( select count(1) from Orders as o where c.id=o.CustomerId)=0
29 |
30 | select c.name as Customers from Customers as c left join Orders as o on o.CustomerId = c.id where o.CustomerId is null;
31 | ```
32 |
--------------------------------------------------------------------------------
/分数排名.md:
--------------------------------------------------------------------------------
1 | # 分数排名
2 |
3 | 编写一个 SQL 查询来实现分数排名。如果两个分数相同,则两个分数排名(Rank)相同。请注意,平分后的下一个名次应该是下一个连续的整数值。换句话说,名次之间不应该有“间隔”。
4 |
5 | | Id | Score |
6 | |——|———|
7 | | 1 | 3.50 |
8 | | 2 | 3.65 |
9 | | 3 | 4.00 |
10 | | 4 | 3.85 |
11 | | 5 | 4.00 |
12 | | 6 | 3.65 |
13 |
14 | 例如,根据上述给定的Scores表,你的查询应该返回(按分数从高到低排列):
15 |
16 | | Score | Rank |
17 | |———|———|
18 | | 4.00 | 1 |
19 | | 4.00 | 1 |
20 | | 3.85 | 2 |
21 | |3.65 | 3 |
22 | | 3.65 | 3 |
23 | | 3.50 | 4 |
24 |
25 |
26 | ```
27 | SELECT Score
28 | , (
29 | SELECT COUNT(DISTINCT Score)
30 | FROM Scores
31 | WHERE Score >= s.Score
32 | ) AS Rank
33 | FROM Scores s
34 | ORDER BY s.Score DESC;
35 | ```
36 |
37 |
--------------------------------------------------------------------------------
/删除重复的电子邮箱.md:
--------------------------------------------------------------------------------
1 | 删除重复的电子邮箱
2 |
3 | 编写一个 SQL 查询,来删除 Person 表中所有重复的电子邮箱,重复的邮箱里只保留 Id 最小 的那个。
4 |
5 | | Id | Email |
6 | |----|------------------|
7 | | 1 | john@example.com |
8 | | 2 | bob@example.com |
9 | | 3 | john@example.com |
10 |
11 | Id 是这个表的主键。
12 | 例如,在运行你的查询语句之后,上面的 Person 表应返回以下几行:
13 |
14 | | Id | Email |
15 | |----|------------------|
16 | | 1 | john@example.com |
17 | | 2 | bob@example.com |
18 |
19 | ` DELETE P1 FROM Person P1,Person p2, where P1.Email = P2.Email AND P1.Id > P2.id;`
20 |
--------------------------------------------------------------------------------
/大的国家.md:
--------------------------------------------------------------------------------
1 | 大的国家
2 |
3 | 这里有张 World 表
4 |
5 |
6 | | name | continent | area | population | gdp |
7 | |-----------------|------------|------------|--------------|---------------|
8 | | Afghanistan | Asia | 652230 | 25500100 | 20343000 |
9 | | Albania | Europe | 28748 | 2831741 | 12960000 |
10 | | Algeria | Africa | 2381741 | 37100000 | 188681000 |
11 | | Andorra | Europe | 468 | 78115 | 3712000 |
12 | | Angola | Africa | 1246700 | 20609294 | 100990000 |
13 |
14 |
15 | 如果一个国家的面积超过300万平方公里,或者人口超过2500万,那么这个国家就是大国家。
16 |
17 | 编写一个SQL查询,输出表中所有大国家的名称、人口和面积。
18 |
19 | 例如,根据上表,我们应该输出:
20 |
21 | | name | population | area |
22 | |--------------|-------------|--------------|
23 | | Afghanistan | 25500100 | 652230 |
24 | | Algeria | 37100000 | 2381741 |
25 |
26 |
27 | ```
28 | select name,population,area from World where area > 3000000 or population > 25000000;
29 | ```
30 |
--------------------------------------------------------------------------------
/有趣的电影.md:
--------------------------------------------------------------------------------
1 | 有趣的电影
2 |
3 | 某城市开了一家新的电影院,吸引了很多人过来看电影。该电影院特别注意用户体验,专门有个 LED显示板做电影推荐,上面公布着影评和相关电影描述。
4 | 作为该电影院的信息部主管,您需要编写一个 SQL查询,找出所有影片描述为非 boring (不无聊) 的并且 id 为奇数 的影片,结果请按等级 rating 排列。
5 | 例如,下表 cinema:
6 |
7 | | id | movie | description | rating |
8 | |---------|-----------|--------------|-----------|
9 | | 1 | War | great 3D | 8.9 |
10 | | 2 | Science | fiction | 8.5 |
11 | | 3 | irish | boring | 6.2 |
12 | | 4 | Ice song | Fantacy | 8.6 |
13 | | 5 | House card| Interesting| 9.1 |
14 |
15 | 对于上面的例子,则正确的输出是为:
16 |
17 | | id | movie | description | rating |
18 | |---------|-----------|--------------|-----------|
19 | | 5 | House card| Interesting| 9.1 |
20 | | 1 | War | great 3D | 8.9 |
21 |
22 | ` select id, movie,description,rating from cinema where description != 'boring' and id&1 order by rating desc; `
23 | ` select * from cinema where mod(id, 2) = 1 and description != 'boring' order by rating DESC; `
24 |
--------------------------------------------------------------------------------
/查找重复的电子邮箱.md:
--------------------------------------------------------------------------------
1 | 查找重复的电子邮箱
2 |
3 | 编写一个 SQL 查询,查找 Person 表中所有重复的电子邮箱。
4 | 如下表:
5 |
6 | | Id | Email |
7 | |----|---------|
8 | | 1 | a@b.com |
9 | | 2 | c@d.com |
10 | | 3 | a@b.com |
11 |
12 | 根据以上输入,你的查询应返回以下结果:
13 |
14 | | Email |
15 | |---------|
16 | | a@b.com |
17 |
18 | ` select Email from Person group by Email having count(*) > 1; `
19 |
--------------------------------------------------------------------------------
/查询01课程比02课程成绩高的学生信息和课程分数.md:
--------------------------------------------------------------------------------
1 | 从不订购的客户
2 |
3 | 查询课程01比课程02成绩高的学生信息和课程分数。
4 |
5 | student 表:
6 |
7 | ```
8 | CREATE TABLE `student` (
9 | `s_id` varchar(20) NOT NULL,
10 | `s_name` varchar(20) NOT NULL DEFAULT '',
11 | `s_birth` varchar(20) NOT NULL DEFAULT '',
12 | `s_sex` varchar(10) NOT NULL DEFAULT '',
13 | PRIMARY KEY (`s_id`)
14 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
15 | ```
16 |
17 | score 表
18 | ```
19 | CREATE TABLE `score` (
20 | `s_id` varchar(20) NOT NULL,
21 | `c_id` varchar(20) NOT NULL,
22 | `s_score` int(3) DEFAULT NULL,
23 | PRIMARY KEY (`s_id`,`c_id`)
24 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
25 | ```
26 |
27 | course 表
28 | ```
29 | CREATE TABLE `course` (
30 | `c_id` varchar(20) NOT NULL,
31 | `c_name` varchar(20) NOT NULL DEFAULT '',
32 | `t_id` varchar(20) NOT NULL,
33 | PRIMARY KEY (`c_id`)
34 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
35 | ```
36 |
37 | 结果:
38 |
39 |
40 | | s_id | s_name | s_sex | 01_score |02_score|s_birth|
41 | |----|---|----|-----|----|-----|
42 | | 02 | 姓名 |性别|成绩1|成绩2|出生日期|
43 | | 04 | 姓名 |性别|成绩1|成绩2|出生日期|
44 |
45 |
46 | ```
47 | SELECT a.* ,
48 | b.s_score AS 01_score,
49 | c.s_score AS 02_score
50 | FROM student a
51 | JOIN score b
52 | ON a.s_id=b.s_id
53 | AND b.c_id='01'
54 | LEFT JOIN score c
55 | ON a.s_id=c.s_id
56 | AND c.c_id='02'
57 | OR c.c_id = NULL
58 | WHERE b.s_score>c.s_score;
59 | ```
--------------------------------------------------------------------------------
/第N高的薪水.md:
--------------------------------------------------------------------------------
1 |
2 | 第N高的薪水
3 |
4 | 编写一个 SQL 查询,获取 Employee 表中第 n 高的薪水(Salary)。
5 |
6 | | Id | Salary |
7 | |----|--------|
8 | | 1 | 100 |
9 | | 2 | 200 |
10 | | 3 | 300 |
11 |
12 | 例如上述 Employee 表,n = 2 时,应返回第二高的薪水 200。如果不存在第 n 高的薪水,那么查询应返回 null。
13 |
14 | | getNthHighestSalary(2) |
15 | |------------------------|
16 | | 200 |
17 |
18 |
19 | ```
20 | select distinct Salary from Employee as e where N = (select count(distinct (Salary)) from Employee where Salary >= e.Salary )
21 | ```
--------------------------------------------------------------------------------
/第二高的薪水.md:
--------------------------------------------------------------------------------
1 | 第二高的薪水
2 |
3 | 编写一个 SQL 查询,获取 Employee 表中第二高的薪水(Salary)。
4 |
5 | | Id | Salary |
6 | |----|---------|
7 | | 1 | 100 |
8 | | 2 | 200 |
9 | | 3 | 300 |
10 |
11 | 例如上述 Employee 表,SQL查询应该返回 200 作为第二高的薪水。如果不存在第二高的薪水,那么查询应返回 null。
12 |
13 | | SecondHighestSalary |
14 | |-------------|
15 | | 200 |
16 |
17 |
18 | ```
19 | IFNULL(field,Default) as alias 的使用方法
20 |
21 | SELECT IFNULL((
22 | SELECT DISTINCT Salary
23 | FROM Employee
24 | ORDER BY Salary DESC
25 | LIMIT 1, 1
26 | ), NULL) AS SecondHighestSalary
27 |
28 |
29 | SELECT DISTINCT Salary AS SecondHighestSalary
30 | FROM Employee
31 | ORDER BY Salary DESC
32 | LIMIT 1, 1
33 | ```
--------------------------------------------------------------------------------
/组合两个表.md:
--------------------------------------------------------------------------------
1 | 组合两个表
2 | 表1: Person
3 |
4 |
5 | | 列名 | 类型 |
6 | |-------------|---------|
7 | | PersonId | int |
8 | | FirstName | varchar |
9 | | LastName | varchar |
10 |
11 | PersonId 是上表主键
12 |
13 | 表2: Address
14 |
15 |
16 | | 列名 | 类型 |
17 | |-------------|---------|
18 | | AddressId | int |
19 | | PersonId | int |
20 | | City | varchar |
21 | | State | varchar |
22 |
23 | AddressId 是上表主键
24 |
25 | 编写一个 SQL 查询,满足条件:无论 person 是否有地址信息,都需要基于上述两表提供 person 的以下信息:
26 |
27 | ` FirstName, LastName, City, State `
28 |
29 | ```
30 | SELECT FirstName, LastName, City, State
31 | FROM Person
32 | LEFT JOIN Address ON Person.PersonId = Address.PersonId;
33 | ```
--------------------------------------------------------------------------------
/超过5名学生的课.md:
--------------------------------------------------------------------------------
1 | 超过5名学生的课
2 |
3 | 有一个courses 表 ,有: student (学生) 和 class (课程)。
4 |
5 | 请列出所有超过或等于5名学生的课。
6 |
7 | 例如,表:
8 |
9 | | student | class |
10 | |---------|------------|
11 | | A | Math |
12 | | B | English |
13 | | C | Math |
14 | | D | Biology |
15 | | E | Math |
16 | | F | Computer |
17 | | G | Math |
18 | | H | Math |
19 | | I | Math |
20 |
21 |
22 | 应该输出:
23 |
24 |
25 | | class |
26 | |---------|
27 | | Math |
28 |
29 |
30 | Note:
31 | 学生在每个课程中不应该重复被计算
32 |
33 | ```
34 | SELECT class
35 | FROM courses
36 | GROUP BY class
37 | HAVING COUNT(DISTINCT student) > 4;
38 | ```
--------------------------------------------------------------------------------
/超过经理收入的员工.md:
--------------------------------------------------------------------------------
1 | 超过经理收入的员工
2 |
3 | Employee 表包含所有员工,他们的经理也属于员工。每个员工都有一个 Id,此外还有一列对应员工的经理的 Id。
4 | 表结构如下
5 |
6 | | Id | Name | Salary | ManagerId |
7 | |----|-------|--------|-----------|
8 | | 1 | Joe | 70000 | 3 |
9 | | 2 | Henry | 80000 | 4 |
10 | | 3 | Sam | 60000 | NULL |
11 | | 4 | Max | 90000 | NULL |
12 |
13 | 给定 Employee 表,编写一个 SQL 查询,该查询可以获取收入超过他们经理的员工的姓名。在上面的表格中,Joe 是唯一一个收入超过他的经理的员工。
14 |
15 | 结果如下:
16 |
17 | | Employee |
18 | |----------|
19 | | Joe |
20 |
21 | ` select e.Name as Employee from Employee as e,Employee as e1 where e.ManagerId = e1.Id and e.Salary > e1.Salary; `
22 |
--------------------------------------------------------------------------------
/部门工资最高的员工.md:
--------------------------------------------------------------------------------
1 | 部门工资最高的员工
2 |
3 |
4 | Employee 表包含所有员工信息,每个员工有其对应的 Id, salary 和 department Id。
5 |
6 |
7 | | Id | Name | Salary | DepartmentId |
8 | |----|-------|--------|--------------|
9 | | 1 | Joe | 70000 | 1 |
10 | | 2 | Henry | 80000 | 2 |
11 | | 3 | Sam | 60000 | 2 |
12 | | 4 | Max | 90000 | 1 |
13 |
14 |
15 | Department 表包含公司所有部门的信息。
16 |
17 | | Id | Name |
18 | |----|----------|
19 | | 1 | IT |
20 | | 2 | Sales |
21 |
22 |
23 | 编写一个 SQL 查询,找出每个部门工资最高的员工。例如,根据上述给定的表格,Max 在 IT 部门有最高工资,Henry 在 Sales 部门有最高工资。
24 |
25 | | Department | Employee | Salary |
26 | |------------|----------|--------|
27 | | IT | Max | 90000 |
28 | | Sales | Henry | 80000 |
29 |
30 | ```
31 | SELECT d.Name AS Department, e.Name AS Employee, e.Salary AS Salary
32 | FROM Employee e
33 | LEFT JOIN Department d ON d.id = e.DepartmentId
34 | WHERE e.Salary = (
35 | SELECT MAX(Salary)
36 | FROM Employee
37 | WHERE DepartmentId = d.Id
38 | );
39 |
40 | SELECT d.Name AS Department, e.Name AS Employee, e.Salary AS Salary
41 | FROM Employee e
42 | INNER JOIN Department d
43 | WHERE d.id = e.DepartmentId
44 | AND e.Salary = (
45 | SELECT MAX(Salary)
46 | FROM Employee
47 | WHERE DepartmentId = d.Id
48 | );
49 | ```
50 |
--------------------------------------------------------------------------------