https://leetcode.com/problems/big-countries/description/

Description

  1. +-----------------+------------+------------+--------------+---------------+
  2. | name | continent | area | population | gdp |
  3. +-----------------+------------+------------+--------------+---------------+
  4. | Afghanistan | Asia | 652230 | 25500100 | 20343000 |
  5. | Albania | Europe | 28748 | 2831741 | 12960000 |
  6. | Algeria | Africa | 2381741 | 37100000 | 188681000 |
  7. | Andorra | Europe | 468 | 78115 | 3712000 |
  8. | Angola | Africa | 1246700 | 20609294 | 100990000 |
  9. +-----------------+------------+------------+--------------+---------------+

查找面积超过 3,000,000 或者人口数超过 25,000,000 的国家。

  1. +--------------+-------------+--------------+
  2. | name | population | area |
  3. +--------------+-------------+--------------+
  4. | Afghanistan | 25500100 | 652230 |
  5. | Algeria | 37100000 | 2381741 |
  6. +--------------+-------------+--------------+

Solution

  1. SELECT name,
  2. population,
  3. area
  4. FROM
  5. World
  6. WHERE
  7. area > 3000000
  8. OR population > 25000000;

SQL Schema

SQL Schema 用于在本地环境下创建表结构并导入数据,从而方便在本地环境调试。

  1. DROP TABLE
  2. IF
  3. EXISTS World;
  4. CREATE TABLE World ( NAME VARCHAR ( 255 ), continent VARCHAR ( 255 ), area INT, population INT, gdp INT );
  5. INSERT INTO World ( NAME, continent, area, population, gdp )
  6. VALUES
  7. ( 'Afghanistan', 'Asia', '652230', '25500100', '203430000' ),
  8. ( 'Albania', 'Europe', '28748', '2831741', '129600000' ),
  9. ( 'Algeria', 'Africa', '2381741', '37100000', '1886810000' ),
  10. ( 'Andorra', 'Europe', '468', '78115', '37120000' ),
  11. ( 'Angola', 'Africa', '1246700', '20609294', '1009900000' );

627. Swap Salary

https://leetcode.com/problems/swap-salary/description/

Description

  1. | id | name | sex | salary |
  2. |----|------|-----|--------|
  3. | 1 | A | m | 2500 |
  4. | 2 | B | f | 1500 |
  5. | 3 | C | m | 5500 |
  6. | 4 | D | f | 500 |

只用一个 SQL 查询,将 sex 字段反转。

  1. | id | name | sex | salary |
  2. |----|------|-----|--------|
  3. | 1 | A | f | 2500 |
  4. | 2 | B | m | 1500 |
  5. | 3 | C | f | 5500 |
  6. | 4 | D | m | 500 |

Solution

两个相等的数异或的结果为 0,而 0 与任何一个数异或的结果为这个数。

sex 字段只有两个取值:’f’ 和 ‘m’,并且有以下规律:

  1. 'f' ^ ('m' ^ 'f') = 'm' ^ ('f' ^ 'f') = 'm'
  2. 'm' ^ ('m' ^ 'f') = 'f' ^ ('m' ^ 'm') = 'f'

因此将 sex 字段和 ‘m’ ^ ‘f’ 进行异或操作,最后就能反转 sex 字段。

  1. UPDATE salary
  2. SET sex = CHAR ( ASCII(sex) ^ ASCII( 'm' ) ^ ASCII( 'f' ) );

SQL Schema

  1. DROP TABLE
  2. IF
  3. EXISTS salary;
  4. CREATE TABLE salary ( id INT, NAME VARCHAR ( 100 ), sex CHAR ( 1 ), salary INT );
  5. INSERT INTO salary ( id, NAME, sex, salary )
  6. VALUES
  7. ( '1', 'A', 'm', '2500' ),
  8. ( '2', 'B', 'f', '1500' ),
  9. ( '3', 'C', 'm', '5500' ),
  10. ( '4', 'D', 'f', '500' );

620. Not Boring Movies

https://leetcode.com/problems/not-boring-movies/description/

Description

  1. +---------+-----------+--------------+-----------+
  2. | id | movie | description | rating |
  3. +---------+-----------+--------------+-----------+
  4. | 1 | War | great 3D | 8.9 |
  5. | 2 | Science | fiction | 8.5 |
  6. | 3 | irish | boring | 6.2 |
  7. | 4 | Ice song | Fantacy | 8.6 |
  8. | 5 | House card| Interesting| 9.1 |
  9. +---------+-----------+--------------+-----------+

查找 id 为奇数,并且 description 不是 boring 的电影,按 rating 降序。

  1. +---------+-----------+--------------+-----------+
  2. | id | movie | description | rating |
  3. +---------+-----------+--------------+-----------+
  4. | 5 | House card| Interesting| 9.1 |
  5. | 1 | War | great 3D | 8.9 |
  6. +---------+-----------+--------------+-----------+

Solution

  1. SELECT
  2. *
  3. FROM
  4. cinema
  5. WHERE
  6. id % 2 = 1
  7. AND description != 'boring'
  8. ORDER BY
  9. rating DESC;

SQL Schema

  1. DROP TABLE
  2. IF
  3. EXISTS cinema;
  4. CREATE TABLE cinema ( id INT, movie VARCHAR ( 255 ), description VARCHAR ( 255 ), rating FLOAT ( 2, 1 ) );
  5. INSERT INTO cinema ( id, movie, description, rating )
  6. VALUES
  7. ( 1, 'War', 'great 3D', 8.9 ),
  8. ( 2, 'Science', 'fiction', 8.5 ),
  9. ( 3, 'irish', 'boring', 6.2 ),
  10. ( 4, 'Ice song', 'Fantacy', 8.6 ),
  11. ( 5, 'House card', 'Interesting', 9.1 );

596. Classes More Than 5 Students

https://leetcode.com/problems/classes-more-than-5-students/description/

Description

  1. +---------+------------+
  2. | student | class |
  3. +---------+------------+
  4. | A | Math |
  5. | B | English |
  6. | C | Math |
  7. | D | Biology |
  8. | E | Math |
  9. | F | Computer |
  10. | G | Math |
  11. | H | Math |
  12. | I | Math |
  13. +---------+------------+

查找有五名及以上 student 的 class。

  1. +---------+
  2. | class |
  3. +---------+
  4. | Math |
  5. +---------+

Solution

对 class 列进行分组之后,再使用 count 汇总函数统计每个分组的记录个数,之后使用 HAVING 进行筛选。HAVING 针对分组进行筛选,而 WHERE 针对每个记录(行)进行筛选。

  1. SELECT
  2. class
  3. FROM
  4. courses
  5. GROUP BY
  6. class
  7. HAVING
  8. count( DISTINCT student ) >= 5;

SQL Schema

  1. DROP TABLE
  2. IF
  3. EXISTS courses;
  4. CREATE TABLE courses ( student VARCHAR ( 255 ), class VARCHAR ( 255 ) );
  5. INSERT INTO courses ( student, class )
  6. VALUES
  7. ( 'A', 'Math' ),
  8. ( 'B', 'English' ),
  9. ( 'C', 'Math' ),
  10. ( 'D', 'Biology' ),
  11. ( 'E', 'Math' ),
  12. ( 'F', 'Computer' ),
  13. ( 'G', 'Math' ),
  14. ( 'H', 'Math' ),
  15. ( 'I', 'Math' );

182. Duplicate Emails

https://leetcode.com/problems/duplicate-emails/description/

Description

邮件地址表:

  1. +----+---------+
  2. | Id | Email |
  3. +----+---------+
  4. | 1 | a@b.com |
  5. | 2 | c@d.com |
  6. | 3 | a@b.com |
  7. +----+---------+

查找重复的邮件地址:

  1. +---------+
  2. | Email |
  3. +---------+
  4. | a@b.com |
  5. +---------+

Solution

对 Email 进行分组,如果并使用 COUNT 进行计数统计,结果大于等于 2 的表示 Email 重复。

  1. SELECT
  2. Email
  3. FROM
  4. Person
  5. GROUP BY
  6. Email
  7. HAVING
  8. COUNT( * ) >= 2;

SQL Schema

  1. DROP TABLE
  2. IF
  3. EXISTS Person;
  4. CREATE TABLE Person ( Id INT, Email VARCHAR ( 255 ) );
  5. INSERT INTO Person ( Id, Email )
  6. VALUES
  7. ( 1, 'a@b.com' ),
  8. ( 2, 'c@d.com' ),
  9. ( 3, 'a@b.com' );

196. Delete Duplicate Emails

https://leetcode.com/problems/delete-duplicate-emails/description/

Description

邮件地址表:

  1. +----+---------+
  2. | Id | Email |
  3. +----+---------+
  4. | 1 | john@example.com |
  5. | 2 | bob@example.com |
  6. | 3 | john@example.com |
  7. +----+---------+

删除重复的邮件地址:

  1. +----+------------------+
  2. | Id | Email |
  3. +----+------------------+
  4. | 1 | john@example.com |
  5. | 2 | bob@example.com |
  6. +----+------------------+

Solution

只保留相同 Email 中 Id 最小的那一个,然后删除其它的。

连接查询:

  1. DELETE p1
  2. FROM
  3. Person p1,
  4. Person p2
  5. WHERE
  6. p1.Email = p2.Email
  7. AND p1.Id > p2.Id

子查询:

  1. DELETE
  2. FROM
  3. Person
  4. WHERE
  5. id NOT IN (
  6. SELECT id
  7. FROM (
  8. SELECT min( id ) AS id
  9. FROM Person
  10. GROUP BY email
  11. ) AS m
  12. );

应该注意的是上述解法额外嵌套了一个 SELECT 语句,如果不这么做,会出现错误:You can’t specify target table ‘Person’ for update in FROM clause。以下演示了这种错误解法。

  1. DELETE
  2. FROM
  3. Person
  4. WHERE
  5. id NOT IN (
  6. SELECT min( id ) AS id
  7. FROM Person
  8. GROUP BY email
  9. );

参考:pMySQL Error 1093 - Can’t specify target table for update in FROM clause

SQL Schema

与 182 相同。

175. Combine Two Tables

https://leetcode.com/problems/combine-two-tables/description/

Description

Person 表:

  1. +-------------+---------+
  2. | Column Name | Type |
  3. +-------------+---------+
  4. | PersonId | int |
  5. | FirstName | varchar |
  6. | LastName | varchar |
  7. +-------------+---------+
  8. PersonId is the primary key column for this table.

Address 表:

  1. +-------------+---------+
  2. | Column Name | Type |
  3. +-------------+---------+
  4. | AddressId | int |
  5. | PersonId | int |
  6. | City | varchar |
  7. | State | varchar |
  8. +-------------+---------+
  9. AddressId is the primary key column for this table.

查找 FirstName, LastName, City, State 数据,而不管一个用户有没有填地址信息。

Solution

涉及到 Person 和 Address 两个表,在对这两个表执行连接操作时,因为要保留 Person 表中的信息,即使在 Address 表中没有关联的信息也要保留。此时可以用左外连接,将 Person 表放在 LEFT JOIN 的左边。

  1. SELECT
  2. FirstName,
  3. LastName,
  4. City,
  5. State
  6. FROM
  7. Person P
  8. LEFT JOIN Address A
  9. ON P.PersonId = A.PersonId;

SQL Schema

  1. DROP TABLE
  2. IF
  3. EXISTS Person;
  4. CREATE TABLE Person ( PersonId INT, FirstName VARCHAR ( 255 ), LastName VARCHAR ( 255 ) );
  5. DROP TABLE
  6. IF
  7. EXISTS Address;
  8. CREATE TABLE Address ( AddressId INT, PersonId INT, City VARCHAR ( 255 ), State VARCHAR ( 255 ) );
  9. INSERT INTO Person ( PersonId, LastName, FirstName )
  10. VALUES
  11. ( 1, 'Wang', 'Allen' );
  12. INSERT INTO Address ( AddressId, PersonId, City, State )
  13. VALUES
  14. ( 1, 2, 'New York City', 'New York' );

181. Employees Earning More Than Their Managers

https://leetcode.com/problems/employees-earning-more-than-their-managers/description/

Description

Employee 表:

  1. +----+-------+--------+-----------+
  2. | Id | Name | Salary | ManagerId |
  3. +----+-------+--------+-----------+
  4. | 1 | Joe | 70000 | 3 |
  5. | 2 | Henry | 80000 | 4 |
  6. | 3 | Sam | 60000 | NULL |
  7. | 4 | Max | 90000 | NULL |
  8. +----+-------+--------+-----------+

查找薪资大于其经理薪资的员工信息。

Solution

  1. SELECT
  2. E1.NAME AS Employee
  3. FROM
  4. Employee E1
  5. INNER JOIN Employee E2
  6. ON E1.ManagerId = E2.Id
  7. AND E1.Salary > E2.Salary;

SQL Schema

  1. DROP TABLE
  2. IF
  3. EXISTS Employee;
  4. CREATE TABLE Employee ( Id INT, NAME VARCHAR ( 255 ), Salary INT, ManagerId INT );
  5. INSERT INTO Employee ( Id, NAME, Salary, ManagerId )
  6. VALUES
  7. ( 1, 'Joe', 70000, 3 ),
  8. ( 2, 'Henry', 80000, 4 ),
  9. ( 3, 'Sam', 60000, NULL ),
  10. ( 4, 'Max', 90000, NULL );

183. Customers Who Never Order

https://leetcode.com/problems/customers-who-never-order/description/

Description

Customers 表:

  1. +----+-------+
  2. | Id | Name |
  3. +----+-------+
  4. | 1 | Joe |
  5. | 2 | Henry |
  6. | 3 | Sam |
  7. | 4 | Max |
  8. +----+-------+

Orders 表:

  1. +----+------------+
  2. | Id | CustomerId |
  3. +----+------------+
  4. | 1 | 3 |
  5. | 2 | 1 |
  6. +----+------------+

查找没有订单的顾客信息:

  1. +-----------+
  2. | Customers |
  3. +-----------+
  4. | Henry |
  5. | Max |
  6. +-----------+

Solution

左外链接

  1. SELECT
  2. C.Name AS Customers
  3. FROM
  4. Customers C
  5. LEFT JOIN Orders O
  6. ON C.Id = O.CustomerId
  7. WHERE
  8. O.CustomerId IS NULL;

子查询

  1. SELECT
  2. Name AS Customers
  3. FROM
  4. Customers
  5. WHERE
  6. Id NOT IN (
  7. SELECT CustomerId
  8. FROM Orders
  9. );

SQL Schema

  1. DROP TABLE
  2. IF
  3. EXISTS Customers;
  4. CREATE TABLE Customers ( Id INT, NAME VARCHAR ( 255 ) );
  5. DROP TABLE
  6. IF
  7. EXISTS Orders;
  8. CREATE TABLE Orders ( Id INT, CustomerId INT );
  9. INSERT INTO Customers ( Id, NAME )
  10. VALUES
  11. ( 1, 'Joe' ),
  12. ( 2, 'Henry' ),
  13. ( 3, 'Sam' ),
  14. ( 4, 'Max' );
  15. INSERT INTO Orders ( Id, CustomerId )
  16. VALUES
  17. ( 1, 3 ),
  18. ( 2, 1 );

184. Department Highest Salary

https://leetcode.com/problems/department-highest-salary/description/

Description

Employee 表:

  1. +----+-------+--------+--------------+
  2. | Id | Name | Salary | DepartmentId |
  3. +----+-------+--------+--------------+
  4. | 1 | Joe | 70000 | 1 |
  5. | 2 | Henry | 80000 | 2 |
  6. | 3 | Sam | 60000 | 2 |
  7. | 4 | Max | 90000 | 1 |
  8. +----+-------+--------+--------------+

Department 表:

  1. +----+----------+
  2. | Id | Name |
  3. +----+----------+
  4. | 1 | IT |
  5. | 2 | Sales |
  6. +----+----------+

查找一个 Department 中收入最高者的信息:

  1. +------------+----------+--------+
  2. | Department | Employee | Salary |
  3. +------------+----------+--------+
  4. | IT | Max | 90000 |
  5. | Sales | Henry | 80000 |
  6. +------------+----------+--------+

Solution

创建一个临时表,包含了部门员工的最大薪资。可以对部门进行分组,然后使用 MAX() 汇总函数取得最大薪资。

之后使用连接找到一个部门中薪资等于临时表中最大薪资的员工。

  1. SELECT
  2. D.NAME Department,
  3. E.NAME Employee,
  4. E.Salary
  5. FROM
  6. Employee E,
  7. Department D,
  8. ( SELECT DepartmentId, MAX( Salary ) Salary
  9. FROM Employee
  10. GROUP BY DepartmentId ) M
  11. WHERE
  12. E.DepartmentId = D.Id
  13. AND E.DepartmentId = M.DepartmentId
  14. AND E.Salary = M.Salary;

SQL Schema

  1. DROP TABLE IF EXISTS Employee;
  2. CREATE TABLE Employee ( Id INT, NAME VARCHAR ( 255 ), Salary INT, DepartmentId INT );
  3. DROP TABLE IF EXISTS Department;
  4. CREATE TABLE Department ( Id INT, NAME VARCHAR ( 255 ) );
  5. INSERT INTO Employee ( Id, NAME, Salary, DepartmentId )
  6. VALUES
  7. ( 1, 'Joe', 70000, 1 ),
  8. ( 2, 'Henry', 80000, 2 ),
  9. ( 3, 'Sam', 60000, 2 ),
  10. ( 4, 'Max', 90000, 1 );
  11. INSERT INTO Department ( Id, NAME )
  12. VALUES
  13. ( 1, 'IT' ),
  14. ( 2, 'Sales' );

176. Second Highest Salary

https://leetcode.com/problems/second-highest-salary/description/

Description

  1. +----+--------+
  2. | Id | Salary |
  3. +----+--------+
  4. | 1 | 100 |
  5. | 2 | 200 |
  6. | 3 | 300 |
  7. +----+--------+

查找工资第二高的员工。

  1. +---------------------+
  2. | SecondHighestSalary |
  3. +---------------------+
  4. | 200 |
  5. +---------------------+

没有找到返回 null 而不是不返回数据。

Solution

为了在没有查找到数据时返回 null,需要在查询结果外面再套一层 SELECT。

  1. SELECT
  2. ( SELECT DISTINCT Salary
  3. FROM Employee
  4. ORDER BY Salary DESC
  5. LIMIT 1, 1 ) SecondHighestSalary;

SQL Schema

  1. DROP TABLE
  2. IF
  3. EXISTS Employee;
  4. CREATE TABLE Employee ( Id INT, Salary INT );
  5. INSERT INTO Employee ( Id, Salary )
  6. VALUES
  7. ( 1, 100 ),
  8. ( 2, 200 ),
  9. ( 3, 300 );

177. Nth Highest Salary

Description

查找工资第 N 高的员工。

Solution

  1. CREATE FUNCTION getNthHighestSalary ( N INT ) RETURNS INT BEGIN
  2. SET N = N - 1;
  3. RETURN (
  4. SELECT (
  5. SELECT DISTINCT Salary
  6. FROM Employee
  7. ORDER BY Salary DESC
  8. LIMIT N, 1
  9. )
  10. );
  11. END

SQL Schema

同 176。

178. Rank Scores

https://leetcode.com/problems/rank-scores/description/

Description

得分表:

  1. +----+-------+
  2. | Id | Score |
  3. +----+-------+
  4. | 1 | 3.50 |
  5. | 2 | 3.65 |
  6. | 3 | 4.00 |
  7. | 4 | 3.85 |
  8. | 5 | 4.00 |
  9. | 6 | 3.65 |
  10. +----+-------+

将得分排序,并统计排名。

  1. +-------+------+
  2. | Score | Rank |
  3. +-------+------+
  4. | 4.00 | 1 |
  5. | 4.00 | 1 |
  6. | 3.85 | 2 |
  7. | 3.65 | 3 |
  8. | 3.65 | 3 |
  9. | 3.50 | 4 |
  10. +-------+------+

Solution

要统计某个 score 的排名,只要统计大于等于该 score 的 score 数量。

Id score 大于等于该 score 的 score 数量 排名
1 4.1 3 3
2 4.2 2 2
3 4.3 1 1

使用连接操作找到某个 score 对应的大于等于其值的记录:

  1. SELECT
  2. *
  3. FROM
  4. Scores S1
  5. INNER JOIN Scores S2
  6. ON S1.score <= S2.score
  7. ORDER BY
  8. S1.score DESC, S1.Id;
S1.Id S1.score S2.Id S2.score
3 4.3 3 4.3
2 4.2 2 4.2
2 4.2 3 4.3
1 4.1 1 4.1
1 4.1 2 4.2
1 4.1 3 4.3

可以看到每个 S1.score 都有对应好几条记录,我们再进行分组,并统计每个分组的数量作为 ‘Rank’

  1. SELECT
  2. S1.score 'Score',
  3. COUNT(*) 'Rank'
  4. FROM
  5. Scores S1
  6. INNER JOIN Scores S2
  7. ON S1.score <= S2.score
  8. GROUP BY
  9. S1.id, S1.score
  10. ORDER BY
  11. S1.score DESC, S1.Id;
score Rank
4.3 1
4.2 2
4.1 3

上面的解法看似没问题,但是对于以下数据,它却得到了错误的结果:

Id score
1 4.1
2 4.2
3 4.2
score Rank
4.2 2
4.2 2
4.1 3

而我们希望的结果为:

score Rank
4.2 1
4.2 1
4.1 2

连接情况如下:

S1.Id S1.score S2.Id S2.score
2 4.2 3 4.2
2 4.2 2 4.2
3 4.2 3 4.2
3 4.2 2 4.1
1 4.1 3 4.2
1 4.1 2 4.2
1 4.1 1 4.1

我们想要的结果是,把分数相同的放在同一个排名,并且相同分数只占一个位置,例如上面的分数,Id=2 和 Id=3 的记录都有相同的分数,并且最高,他们并列第一。而 Id=1 的记录应该排第二名,而不是第三名。所以在进行 COUNT 计数统计时,我们需要使用 COUNT( DISTINCT S2.score ) 从而只统计一次相同的分数。

  1. SELECT
  2. S1.score 'Score',
  3. COUNT( DISTINCT S2.score ) 'Rank'
  4. FROM
  5. Scores S1
  6. INNER JOIN Scores S2
  7. ON S1.score <= S2.score
  8. GROUP BY
  9. S1.id, S1.score
  10. ORDER BY
  11. S1.score DESC;

SQL Schema

  1. DROP TABLE
  2. IF
  3. EXISTS Scores;
  4. CREATE TABLE Scores ( Id INT, Score DECIMAL ( 3, 2 ) );
  5. INSERT INTO Scores ( Id, Score )
  6. VALUES
  7. ( 1, 4.1 ),
  8. ( 2, 4.1 ),
  9. ( 3, 4.2 ),
  10. ( 4, 4.2 ),
  11. ( 5, 4.3 ),
  12. ( 6, 4.3 );

180. Consecutive Numbers

https://leetcode.com/problems/consecutive-numbers/description/

Description

数字表:

  1. +----+-----+
  2. | Id | Num |
  3. +----+-----+
  4. | 1 | 1 |
  5. | 2 | 1 |
  6. | 3 | 1 |
  7. | 4 | 2 |
  8. | 5 | 1 |
  9. | 6 | 2 |
  10. | 7 | 2 |
  11. +----+-----+

查找连续出现三次的数字。

  1. +-----------------+
  2. | ConsecutiveNums |
  3. +-----------------+
  4. | 1 |
  5. +-----------------+

Solution

  1. SELECT
  2. DISTINCT L1.num ConsecutiveNums
  3. FROM
  4. Logs L1,
  5. Logs L2,
  6. Logs L3
  7. WHERE L1.id = l2.id - 1
  8. AND L2.id = L3.id - 1
  9. AND L1.num = L2.num
  10. AND l2.num = l3.num;

SQL Schema

  1. DROP TABLE
  2. IF
  3. EXISTS LOGS;
  4. CREATE TABLE LOGS ( Id INT, Num INT );
  5. INSERT INTO LOGS ( Id, Num )
  6. VALUES
  7. ( 1, 1 ),
  8. ( 2, 1 ),
  9. ( 3, 1 ),
  10. ( 4, 2 ),
  11. ( 5, 1 ),
  12. ( 6, 2 ),
  13. ( 7, 2 );

626. Exchange Seats

https://leetcode.com/problems/exchange-seats/description/

Description

seat 表存储着座位对应的学生。

  1. +---------+---------+
  2. | id | student |
  3. +---------+---------+
  4. | 1 | Abbot |
  5. | 2 | Doris |
  6. | 3 | Emerson |
  7. | 4 | Green |
  8. | 5 | Jeames |
  9. +---------+---------+

要求交换相邻座位的两个学生,如果最后一个座位是奇数,那么不交换这个座位上的学生。

  1. +---------+---------+
  2. | id | student |
  3. +---------+---------+
  4. | 1 | Doris |
  5. | 2 | Abbot |
  6. | 3 | Green |
  7. | 4 | Emerson |
  8. | 5 | Jeames |
  9. +---------+---------+

Solution

使用多个 union。

  1. ## 处理偶数 id,让 id 减 1
  2. ## 例如 2,4,6,... 变成 1,3,5,...
  3. SELECT
  4. s1.id - 1 AS id,
  5. s1.student
  6. FROM
  7. seat s1
  8. WHERE
  9. s1.id MOD 2 = 0 UNION
  10. ## 处理奇数 id,让 id 加 1。但是如果最大的 id 为奇数,则不做处理
  11. ## 例如 1,3,5,... 变成 2,4,6,...
  12. SELECT
  13. s2.id + 1 AS id,
  14. s2.student
  15. FROM
  16. seat s2
  17. WHERE
  18. s2.id MOD 2 = 1
  19. AND s2.id != ( SELECT max( s3.id ) FROM seat s3 ) UNION
  20. ## 如果最大的 id 为奇数,单独取出这个数
  21. SELECT
  22. s4.id AS id,
  23. s4.student
  24. FROM
  25. seat s4
  26. WHERE
  27. s4.id MOD 2 = 1
  28. AND s4.id = ( SELECT max( s5.id ) FROM seat s5 )
  29. ORDER BY
  30. id;

SQL Schema

  1. DROP TABLE
  2. IF
  3. EXISTS seat;
  4. CREATE TABLE seat ( id INT, student VARCHAR ( 255 ) );
  5. INSERT INTO seat ( id, student )
  6. VALUES
  7. ( '1', 'Abbot' ),
  8. ( '2', 'Doris' ),
  9. ( '3', 'Emerson' ),
  10. ( '4', 'Green' ),
  11. ( '5', 'Jeames' );