595. Big Countries
https://leetcode.com/problems/big-countries/description/
Description
+-----------------+------------+------------+--------------+---------------+
| name | continent | area | population | gdp |
+-----------------+------------+------------+--------------+---------------+
| Afghanistan | Asia | 652230 | 25500100 | 20343000 |
| Albania | Europe | 28748 | 2831741 | 12960000 |
| Algeria | Africa | 2381741 | 37100000 | 188681000 |
| Andorra | Europe | 468 | 78115 | 3712000 |
| Angola | Africa | 1246700 | 20609294 | 100990000 |
+-----------------+------------+------------+--------------+---------------+
查找面积超过 3,000,000 或者人口数超过 25,000,000 的国家。
+--------------+-------------+--------------+
| name | population | area |
+--------------+-------------+--------------+
| Afghanistan | 25500100 | 652230 |
| Algeria | 37100000 | 2381741 |
+--------------+-------------+--------------+
SQL Schema
DROP TABLE
IF
EXISTS World
;
CREATE TABLE World
( NAME
VARCHAR ( 255 ), continent
VARCHAR ( 255 ), area
INT, population
INT, gdp
INT );
INSERT INTO World
( NAME
, continent
, area
, population
, gdp
)
VALUES
( 'Afghanistan', 'Asia', '652230', '25500100', '203430000' ),
( 'Albania', 'Europe', '28748', '2831741', '129600000' ),
( 'Algeria', 'Africa', '2381741', '37100000', '1886810000' ),
( 'Andorra', 'Europe', '468', '78115', '37120000' ),
( 'Angola', 'Africa', '1246700', '20609294', '1009900000' );
Solution
SELECT name
,
population
,
area
FROM
World
WHERE
area
> 3000000
OR population
> 25000000;
627. Swap Salary
https://leetcode.com/problems/swap-salary/description/
Description
| id | name | sex | salary |
|----|------|-----|--------|
| 1 | A | m | 2500 |
| 2 | B | f | 1500 |
| 3 | C | m | 5500 |
| 4 | D | f | 500 |
只用一个 SQL 查询,将 sex 字段反转。
| id | name | sex | salary |
|----|------|-----|--------|
| 1 | A | f | 2500 |
| 2 | B | m | 1500 |
| 3 | C | f | 5500 |
| 4 | D | m | 500 |
SQL Schema
DROP TABLE
IF
EXISTS salary
;
CREATE TABLE salary
( id
INT, NAME
VARCHAR ( 100 ), sex
CHAR ( 1 ), salary
INT );
INSERT INTO salary
( id
, NAME
, sex
, salary
)
VALUES
( '1', 'A', 'm', '2500' ),
( '2', 'B', 'f', '1500' ),
( '3', 'C', 'm', '5500' ),
( '4', 'D', 'f', '500' );
Solution
UPDATE salary
SET sex
= CHAR ( ASCII
(sex
) ^ ASCII
( 'm' ) ^ ASCII
( 'f' ) );
620. Not Boring Movies
https://leetcode.com/problems/not-boring-movies/description/
Description
+---------+-----------+--------------+-----------+
| id | movie | description | rating |
+---------+-----------+--------------+-----------+
| 1 | War | great 3D | 8.9 |
| 2 | Science | fiction | 8.5 |
| 3 | irish | boring | 6.2 |
| 4 | Ice song | Fantacy | 8.6 |
| 5 | House card| Interesting| 9.1 |
+---------+-----------+--------------+-----------+
查找 id 为奇数,并且 description 不是 boring 的电影,按 rating 降序。
+---------+-----------+--------------+-----------+
| id | movie | description | rating |
+---------+-----------+--------------+-----------+
| 5 | House card| Interesting| 9.1 |
| 1 | War | great 3D | 8.9 |
+---------+-----------+--------------+-----------+
SQL Schema
DROP TABLE
IF
EXISTS cinema
;
CREATE TABLE cinema
( id
INT, movie
VARCHAR ( 255 ), description
VARCHAR ( 255 ), rating
FLOAT ( 2, 1 ) );
INSERT INTO cinema
( id
, movie
, description
, rating
)
VALUES
( 1, 'War', 'great 3D', 8.9 ),
( 2, 'Science', 'fiction', 8.5 ),
( 3, 'irish', 'boring', 6.2 ),
( 4, 'Ice song', 'Fantacy', 8.6 ),
( 5, 'House card', 'Interesting', 9.1 );
Solution
SELECT
*
FROM
cinema
WHERE
id
% 2 = 1
AND description
!= 'boring'
ORDER BY
rating
DESC;
596. Classes More Than 5 Students
https://leetcode.com/problems/classes-more-than-5-students/description/
Description
+---------+------------+
| student | class |
+---------+------------+
| A | Math |
| B | English |
| C | Math |
| D | Biology |
| E | Math |
| F | Computer |
| G | Math |
| H | Math |
| I | Math |
+---------+------------+
查找有五名及以上 student 的 class。
+---------+
| class |
+---------+
| Math |
+---------+
SQL Schema
DROP TABLE
IF
EXISTS courses
;
CREATE TABLE courses
( student
VARCHAR ( 255 ), class
VARCHAR ( 255 ) );
INSERT INTO courses
( student
, class
)
VALUES
( 'A', 'Math' ),
( 'B', 'English' ),
( 'C', 'Math' ),
( 'D', 'Biology' ),
( 'E', 'Math' ),
( 'F', 'Computer' ),
( 'G', 'Math' ),
( 'H', 'Math' ),
( 'I', 'Math' );
Solution
SELECT
class
FROM
courses
GROUP BY
class
HAVING
count( DISTINCT student
) >= 5;
182. Duplicate Emails
https://leetcode.com/problems/duplicate-emails/description/
Description
邮件地址表:
+----+---------+
| Id | Email |
+----+---------+
| 1 | a@b.com |
| 2 | c@d.com |
| 3 | a@b.com |
+----+---------+
查找重复的邮件地址:
+---------+
| Email |
+---------+
| a@b.com |
+---------+
SQL Schema
DROP TABLE
IF
EXISTS Person
;
CREATE TABLE Person
( Id
INT, Email
VARCHAR ( 255 ) );
INSERT INTO Person
( Id
, Email
)
VALUES
( 1, 'a@b.com' ),
( 2, 'c@d.com' ),
( 3, 'a@b.com' );
Solution
SELECT
Email
FROM
Person
GROUP BY
Email
HAVING
COUNT( * ) >= 2;
196. Delete Duplicate Emails
https://leetcode.com/problems/delete-duplicate-emails/description/
Description
邮件地址表:
+----+---------+
| Id | Email |
+----+---------+
| 1 | a@b.com |
| 2 | c@d.com |
| 3 | a@b.com |
+----+---------+
删除重复的邮件地址:
+----+------------------+
| Id | Email |
+----+------------------+
| 1 | john@example.com |
| 2 | bob@example.com |
+----+------------------+
SQL Schema
与 182 相同。
Solution
连接:
DELETE p1
FROM
Person p1
,
Person p2
WHERE
p1
.Email
= p2
.Email
AND p1
.Id
> p2
.Id
子查询:
DELETE
FROM
Person
WHERE
id
NOT IN ( SELECT id
FROM ( SELECT min( id
) AS id
FROM Person
GROUP BY email
) AS m
);
应该注意的是上述解法额外嵌套了一个 SELECT 语句,如果不这么做,会出现错误:You can’t specify target table ‘Person’ for update in FROM clause。以下演示了这种错误解法。
DELETE
FROM
Person
WHERE
id
NOT IN ( SELECT min( id
) AS id
FROM Person
GROUP BY email
);
参考:pMySQL Error 1093 - Can’t specify target table for update in FROM clause
175. Combine Two Tables
https://leetcode.com/problems/combine-two-tables/description/
Description
Person 表:
+-------------+---------+
| Column Name | Type |
+-------------+---------+
| PersonId | int |
| FirstName | varchar |
| LastName | varchar |
+-------------+---------+
PersonId is the primary key column for this table.
Address 表:
+-------------+---------+
| Column Name | Type |
+-------------+---------+
| AddressId | int |
| PersonId | int |
| City | varchar |
| State | varchar |
+-------------+---------+
AddressId is the primary key column for this table.
查找 FirstName, LastName, City, State 数据,而不管一个用户有没有填地址信息。
SQL Schema
DROP TABLE
IF
EXISTS Person
;
CREATE TABLE Person
( PersonId
INT, FirstName
VARCHAR ( 255 ), LastName
VARCHAR ( 255 ) );
DROP TABLE
IF
EXISTS Address
;
CREATE TABLE Address
( AddressId
INT, PersonId
INT, City
VARCHAR ( 255 ), State
VARCHAR ( 255 ) );
INSERT INTO Person
( PersonId
, LastName
, FirstName
)
VALUES
( 1, 'Wang', 'Allen' );
INSERT INTO Address
( AddressId
, PersonId
, City
, State
)
VALUES
( 1, 2, 'New York City', 'New York' );
Solution
使用左外连接。
SELECT
FirstName
,
LastName
,
City
,
State
FROM
Person P
LEFT JOIN Address A
ON P
.PersonId
= A
.PersonId
;
181. Employees Earning More Than Their Managers
https://leetcode.com/problems/employees-earning-more-than-their-managers/description/
Description
Employee 表:
+----+-------+--------+-----------+
| Id | Name | Salary | ManagerId |
+----+-------+--------+-----------+
| 1 | Joe | 70000 | 3 |
| 2 | Henry | 80000 | 4 |
| 3 | Sam | 60000 | NULL |
| 4 | Max | 90000 | NULL |
+----+-------+--------+-----------+
查找薪资大于其经理薪资的员工信息。
SQL Schema
DROP TABLE
IF
EXISTS Employee
;
CREATE TABLE Employee
( Id
INT, NAME
VARCHAR ( 255 ), Salary
INT, ManagerId
INT );
INSERT INTO Employee
( Id
, NAME
, Salary
, ManagerId
)
VALUES
( 1, 'Joe', 70000, 3 ),
( 2, 'Henry', 80000, 4 ),
( 3, 'Sam', 60000, NULL ),
( 4, 'Max', 90000, NULL );
Solution
SELECT
E1
.NAME
AS Employee
FROM
Employee E1
INNER JOIN Employee E2
ON E1
.ManagerId
= E2
.Id
AND E1
.Salary
> E2
.Salary
;
183. Customers Who Never Order
https://leetcode.com/problems/customers-who-never-order/description/
Description
Customers 表:
+----+-------+
| Id | Name |
+----+-------+
| 1 | Joe |
| 2 | Henry |
| 3 | Sam |
| 4 | Max |
+----+-------+
Orders 表:
+----+------------+
| Id | CustomerId |
+----+------------+
| 1 | 3 |
| 2 | 1 |
+----+------------+
查找没有订单的顾客信息:
+-----------+
| Customers |
+-----------+
| Henry |
| Max |
+-----------+
SQL Schema
DROP TABLE
IF
EXISTS Customers
;
CREATE TABLE Customers
( Id
INT, NAME
VARCHAR ( 255 ) );
DROP TABLE
IF
EXISTS Orders
;
CREATE TABLE Orders
( Id
INT, CustomerId
INT );
INSERT INTO Customers
( Id
, NAME
)
VALUES
( 1, 'Joe' ),
( 2, 'Henry' ),
( 3, 'Sam' ),
( 4, 'Max' );
INSERT INTO Orders
( Id
, CustomerId
)
VALUES
( 1, 3 ),
( 2, 1 );
Solution
左外链接
SELECT
C
.Name
AS Customers
FROM
Customers C
LEFT JOIN Orders O
ON C
.Id
= O
.CustomerId
WHERE
O
.CustomerId
IS NULL;
子查询
SELECT
Name
AS Customers
FROM
Customers
WHERE
Id
NOT IN ( SELECT CustomerId
FROM Orders
);
184. Department Highest Salary
https://leetcode.com/problems/department-highest-salary/description/
Description
Employee 表:
+----+-------+--------+--------------+
| 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 |
+----+----------+
查找一个 Department 中收入最高者的信息:
+------------+----------+--------+
| Department | Employee | Salary |
+------------+----------+--------+
| IT | Max | 90000 |
| Sales | Henry | 80000 |
+------------+----------+--------+
SQL Schema
DROP TABLE IF EXISTS Employee
;
CREATE TABLE Employee
( Id
INT, NAME
VARCHAR ( 255 ), Salary
INT, DepartmentId
INT );
DROP TABLE IF EXISTS Department
;
CREATE TABLE Department
( Id
INT, NAME
VARCHAR ( 255 ) );
INSERT INTO Employee
( Id
, NAME
, Salary
, DepartmentId
)
VALUES
( 1, 'Joe', 70000, 1 ),
( 2, 'Henry', 80000, 2 ),
( 3, 'Sam', 60000, 2 ),
( 4, 'Max', 90000, 1 );
INSERT INTO Department
( Id
, NAME
)
VALUES
( 1, 'IT' ),
( 2, 'Sales' );
Solution
创建一个临时表,包含了部门员工的最大薪资。可以对部门进行分组,然后使用 MAX() 汇总函数取得最大薪资。
之后使用连接找到一个部门中薪资等于临时表中最大薪资的员工。
SELECT
D
.NAME Department
,
E
.NAME Employee
,
E
.Salary
FROM
Employee E
,
Department D
,
( SELECT DepartmentId
, MAX( Salary
) Salary
FROM Employee
GROUP BY DepartmentId
) M
WHERE
E
.DepartmentId
= D
.Id
AND E
.DepartmentId
= M
.DepartmentId
AND E
.Salary
= M
.Salary
;
176. Second Highest Salary
https://leetcode.com/problems/second-highest-salary/description/
Description
+----+--------+
| Id | Salary |
+----+--------+
| 1 | 100 |
| 2 | 200 |
| 3 | 300 |
+----+--------+
查找工资第二高的员工。
+---------------------+
| SecondHighestSalary |
+---------------------+
| 200 |
+---------------------+
没有找到返回 null 而不是不返回数据。
SQL Schema
DROP TABLE
IF
EXISTS Employee
;
CREATE TABLE Employee
( Id
INT, Salary
INT );
INSERT INTO Employee
( Id
, Salary
)
VALUES
( 1, 100 ),
( 2, 200 ),
( 3, 300 );
Solution
为了在没有查找到数据时返回 null,需要在查询结果外面再套一层 SELECT。
SELECT
( SELECT DISTINCT Salary
FROM Employee
ORDER BY Salary
DESC LIMIT 1, 1 ) SecondHighestSalary
;
177. Nth Highest Salary
Description
查找工资第 N 高的员工。
SQL Schema
同 176。
Solution
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 ) );
END
178. Rank Scores
https://leetcode.com/problems/rank-scores/description/
Description
得分表:
+----+-------+
| Id | Score |
+----+-------+
| 1 | 3.50 |
| 2 | 3.65 |
| 3 | 4.00 |
| 4 | 3.85 |
| 5 | 4.00 |
| 6 | 3.65 |
+----+-------+
将得分排序,并统计排名。
+-------+------+
| Score | Rank |
+-------+------+
| 4.00 | 1 |
| 4.00 | 1 |
| 3.85 | 2 |
| 3.65 | 3 |
| 3.65 | 3 |
| 3.50 | 4 |
+-------+------+
SQL Schema
DROP TABLE
IF
EXISTS Scores
;
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 );
Solution
SELECT
S1
.score
,
COUNT( DISTINCT S2
.score
) Rank
FROM
Scores S1
INNER JOIN Scores S2
ON S1
.score
<= S2
.score
GROUP BY
S1
.id
, S1
.score
ORDER BY
S1
.score
DESC;
180. Consecutive Numbers
https://leetcode.com/problems/consecutive-numbers/description/
Description
数字表:
+----+-----+
| Id | Num |
+----+-----+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 2 |
| 5 | 1 |
| 6 | 2 |
| 7 | 2 |
+----+-----+
查找连续出现三次的数字。
+-----------------+
| ConsecutiveNums |
+-----------------+
| 1 |
+-----------------+
SQL Schema
DROP TABLE
IF
EXISTS LOGS
;
CREATE TABLE LOGS
( Id
INT, Num
INT );
INSERT INTO LOGS
( Id
, Num
)
VALUES
( 1, 1 ),
( 2, 1 ),
( 3, 1 ),
( 4, 2 ),
( 5, 1 ),
( 6, 2 ),
( 7, 2 );
Solution
SELECT
DISTINCT L1
.num ConsecutiveNums
FROM
Logs L1
,
Logs L2
,
Logs L3
WHERE L1
.id
= l2
.id
- 1
AND L2
.id
= L3
.id
- 1
AND L1
.num
= L2
.num
AND l2
.num
= l3
.num
;
626. Exchange Seats
https://leetcode.com/problems/exchange-seats/description/
Description
seat 表存储着座位对应的学生。
+---------+---------+
| id | student |
+---------+---------+
| 1 | Abbot |
| 2 | Doris |
| 3 | Emerson |
| 4 | Green |
| 5 | Jeames |
+---------+---------+
要求交换相邻座位的两个学生,如果最后一个座位是奇数,那么不交换这个座位上的学生。
+---------+---------+
| id | student |
+---------+---------+
| 1 | Doris |
| 2 | Abbot |
| 3 | Green |
| 4 | Emerson |
| 5 | Jeames |
+---------+---------+
SQL Schema
DROP TABLE
IF
EXISTS seat
;
CREATE TABLE seat
( id
INT, student
VARCHAR ( 255 ) );
INSERT INTO seat
( id
, student
)
VALUES
( '1', 'Abbot' ),
( '2', 'Doris' ),
( '3', 'Emerson' ),
( '4', 'Green' ),
( '5', 'Jeames' );
Solution
使用多个 union。
SELECT
s1
.id
- 1 AS id
,
s1
.student
FROM
seat s1
WHERE
s1
.id MOD
2 = 0 UNION
SELECT
s2
.id
+ 1 AS id
,
s2
.student
FROM
seat s2
WHERE
s2
.id MOD
2 = 1
AND s2
.id
!= ( SELECT max( s3
.id
) FROM seat s3
) UNION
SELECT
s4
.id
AS id
,
s4
.student
FROM
seat s4
WHERE
s4
.id MOD
2 = 1
AND s4
.id
= ( SELECT max( s5
.id
) FROM seat s5
)
ORDER BY
id
;