最近在 leetcode 上刷了一下 database 的题目,做一下总结笔记。

因为贫穷,还写了一个油猴脚本来隐藏掉订阅题目。

交换座位

题目点这里

题目的意思是交换相邻的两个记录的 student 字段,也就是 1 和 2 互换,3 和 4 互换这样子,如果最后一个是奇数,则不理会

比如输入是:

1
2
3
4
id student
1 alice
2 bob
3 tom

期望输出应该是:

1
2
3
4
id student
1 bob
2 alice
3 tom

有两个解法,一个解法是通过控制流程来解决,还有一个比较骚的操作是通过位操作和 COALESCE() 函数来解决。

SQL 代码如下

1
2
3
4
5
6
7
SELECT
s1.id, COALESCE(s2.student, s1.student) AS student
FROM
seat s1
LEFT JOIN
seat s2 ON ((s1.id + 1) ^ 1) - 1 = s2.id
ORDER BY s1.id;
  • 这个解法的思路是将相邻的记录连接起来,连接后的每一行有相邻的两个 id 两个相应的 student 字段,然后拿对应的字段。
  • 使用左连接,左表的 student 一定会有数据,同时使用 COALESCE() 函数来选择 student 字段,优先取右表的 student,当右表的 student 为空,则取左表的 student,也就是用来兼容最后一行记录的 id 是奇数的情况。
  • 连表的条件:f(n) = (n + 1) ^ 1 - 1
    • 当输入为奇数,加一变为偶数,与 1 异或再加一,最后再减一,即为 n + 1
    • 当输入为偶数,加一变为奇数,与 1 异或减一(变为输入),最后再减一,即为 n - 1
    • 使用该公式可以达到 f(1) = 2, f(2) = 1 地效果。

因此,只需要将 1&23&4 这样关系的行记录进行左连接,再将左表的 id 和右表的 student 选择出来,即可达到题目要求。