一、题目
表: Seat
+-------------+---------+
| Column Name | Type |
+-------------+---------+
| id | int |
| name | varchar |
+-------------+---------+
Id是该表的主键列。
该表的每一行都表示学生的姓名和ID。
Id是一个连续的增量。
编写SQL查询来交换每两个连续的学生的座位号。如果学生的数量是奇数,则最后一个学生的id不交换。
按 id 升序 返回结果表。
查询结果格式如下所示。
示例 1:
输入:
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 |
+----+---------+
解释:
请注意,如果学生人数为奇数,则不需要更换最后一名学生的座位。
二、解决
1、if / case when
思路:
主要根据 id 的奇偶性进行处理,这里要注意 id 最大值为基数的情况。
if id 为偶数,then id - 1;
if id为奇数且不为最大值, then id + 1;
if id为奇数且为最大值, then id 不变。
代码 - 版本1:
select
if (id%2=0, id-1,
if(id=mxid, id, id+1)
) as id, student
from seat, (select max(id) as mxid from seat) as init # 最大数为奇数
order by id;
代码 - 版本2:
select
case
when id % 2 = 0 then id - 1
when id % 2 = 1 and id = mxid then id
else id + 1
end as id
, student
from seat, (select max(id) as mxid from seat) as init # 最大数为奇数
order by id;
2、row_number()
思路:
row_number() 作用实例:
SELECT
name, recovery_model_desc
FROM sys.databases
WHERE database_id < 5
ORDER BY name ASC;
Here is the result set.
| name | recovery_model_desc |
|---|---|
| master | SIMPLE |
| model | FULL |
| msdb | SIMPLE |
| tempdb | SIMPLE |
SELECT
ROW_NUMBER() OVER(PARTITION BY recovery_model_desc ORDER BY name ASC)
AS Row#,
name, recovery_model_desc
FROM sys.databases WHERE database_id < 5;
Here is the result set.
| Row# | name | recovery_model_desc |
|---|---|---|
| 1 | model | FULL |
| 1 | master | SIMPLE |
| 2 | msdb | SIMPLE |
| 3 | tempdb | SIMPLE |
代码:
select
row_number() over(order by (id + 1 - 2 * power(0, id%2))) as id,
student
from
seat
说明:
select power(0, 1) as odd, power(0, 0) as even;
# res:
{"headers": ["odd", "even"], "values": [
[0.0, 1.0]
]}
3、left join
思路:
select t1.id, t2.student, t1.student
from seat as t1
left join seat as t2 on (t1.id%2=1 && t1.id=t2.id-1) || (t1.id%2=0 && t1.id=t2.id+1)
order by t1.id;
| a.id | b.student | a.student |
|---|---|---|
| 1 | Doris | Abbot |
| 2 | Abbot | Doris |
| 3 | Green | Emerson |
| 4 | Emerson | Green |
| 5 | null | Jeames |
代码:
select t1.id, ifnull(t2.student, t1.student) as student
from seat as t1
left join seat as t2 on (t1.id%2=1 && t1.id=t2.id-1) || (t1.id%2=0 && t1.id=t2.id+1)
order by t1.id;
4、异或
思路: 0^1=1, 1^1=0, 2^1=3, 3^1=2,以此类推。
代码:
select b.id, a.student
from seat as a, seat as b, (select count(*) as cnt from seat) as c
where b.id = 1^(a.id-1) + 1
# where a.id=1^(b.id-1) + 1 # 也可以这样写,更容易理解.
# If b.id is 偶数, then b.id-1;
# If b.id is 奇数, then b.id+1;
|| (c.cnt%2 && b.id=c.cnt && a.id=c.cnt);
三、参考
1、换座位
2、简单 易懂 效率击败所有
3、其实是一道中学数学题
4、626. 换座位[官方题解的坑要避免]
5、看到没有异或方法,我就知道我的机会来了
这篇博客详细介绍了如何使用SQL解决LeetCode中的626题——交换每两个连续学生座位。作者探讨了四种不同的解决方案,包括if/case when、row_number()、left join以及异或操作,并提供了相应的代码示例。文章强调了针对不同情况(如座位数为奇数)的处理,并引用了其他相关资源作为参考。
769

被折叠的 条评论
为什么被折叠?



