├── 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 | --------------------------------------------------------------------------------