- SQL架构
- 题目描述
- 题解
- 方法一:使用 CASE
- 方法二:使用位操作和 COALESCE()
- 知识点
- coalesce 函数返回其参数中第一个非空表达式
- ^ 按位异或
Create table If Not Exists seat(id int, student varchar(255));
insert into seat (id, student) values ('1', 'Abbot');
insert into seat (id, student) values ('2', 'Doris');
insert into seat (id, student) values ('3', 'Emerson');
insert into seat (id, student) values ('4', 'Green');
insert into seat (id, student) values ('5', 'Jeames');
mysql> SELECT * FROM `seat` LIMIT 0, 1000;
+------+---------+
| id | student |
+------+---------+
| 1 | Abbot |
| 2 | Doris |
| 3 | Emerson |
| 4 | Green |
| 5 | Jeames |
+------+---------+
5 rows in set (0.00 sec)
题目描述
小美是一所中学的信息科技老师,她有一张 seat 座位表,平时用来储存学生名字和与他们相对应的座位 id。
其中纵列的 id 是连续递增的,小美想改变相邻俩学生的座位。
你能不能帮她写一个 SQL query 来输出小美想要的结果呢?
示例:
+---------+---------+
| id | student |
+---------+---------+
| 1 | Abbot |
| 2 | Doris |
| 3 | Emerson |
| 4 | Green |
| 5 | Jeames |
+---------+---------+
假如数据输入的是上表,则输出结果如下:
+---------+---------+
| id | student |
+---------+---------+
| 1 | Doris |
| 2 | Abbot |
| 3 | Green |
| 4 | Emerson |
| 5 | Jeames |
+---------+---------+
注意:
如果学生人数是奇数,则不需要改变最后一个同学的座位。
题解 方法一:使用 CASE算法
对于所有座位 id 是奇数的学生,修改其 id 为 id+1,如果最后一个座位 id 也是奇数,则最后一个座位 id 不修改。对于所有座位 id 是偶数的学生,修改其 id 为 id-1。
首先查询座位的数量。
SELECT
COUNT(*) AS counts
FROM
seat
然后使用 CASE 条件和 MOD 函数修改每个学生的座位 id。
mysql> SELECT * FROM `seat` LIMIT 0, 1000;
+------+---------+
| id | student |
+------+---------+
| 1 | Abbot |
| 2 | Doris |
| 3 | Emerson |
| 4 | Green |
| 5 | Jeames |
+------+---------+
5 rows in set (0.00 sec)
在 MySQL 中求余函数 MOD(x,y) 返回 x 被 y 除后的余数,MOD() 对于带有小数部分的数值也起作用,
它返回除法运算后的余数。
SELECT
(CASE
WHEN MOD(id, 2) != 0 AND counts != id THEN id + 1
WHEN MOD(id, 2) != 0 AND counts = id THEN id
ELSE id - 1
END) AS id,
student
FROM seat,
(SELECT COUNT(*) AS counts FROM seat) AS seat_counts ORDER BY id ASC;
+------+---------+
| id | student |
+------+---------+
| 1 | Doris |
| 2 | Abbot |
| 3 | Green |
| 4 | Emerson |
| 5 | Jeames |
+------+---------+
5 rows in set (0.00 sec)
方法二:使用位操作和 COALESCE()
算法
使用 (id+1)^1-1 计算交换后每个学生的座位 id。
mysql> SELECT id, (id+1)^1-1, student FROM seat;
+------+------------+---------+
| id | (id+1)^1-1 | student |
+------+------------+---------+
| 1 | 2 | Abbot |
| 2 | 1 | Doris |
| 3 | 4 | Emerson |
| 4 | 3 | Green |
| 5 | 6 | Jeames |
+------+------------+---------+
5 rows in set (0.00 sec)
然后连接原来的座位表和更新 id 后的座位表。
SELECT
*
FROM
seat s1
LEFT JOIN
seat s2 ON (s1.id+1)^1-1 = s2.id
ORDER BY s1.id;
+------+---------+------+---------+
| id | student | id | student |
+------+---------+------+---------+
| 1 | Abbot | 2 | Doris |
| 2 | Doris | 1 | Abbot |
| 3 | Emerson | 4 | Green |
| 4 | Green | 3 | Emerson |
| 5 | Jeames | NULL | NULL |
+------+---------+------+---------+
5 rows in set (0.00 sec)
注:前两列来自表 s1,后两列来自表 s2。
最后输出 s1.id 和 s2.student。但是 id=5 的学生,s1.student 正确,s2.student 为 NULL。因此使用 COALESCE() 函数为最后一行记录生成正确的输出。
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 |
+------+---------+
| 1 | Doris |
| 2 | Abbot |
| 3 | Green |
| 4 | Emerson |
| 5 | Jeames |
+------+---------+
5 rows in set (0.00 sec)
知识点
coalesce 函数返回其参数中第一个非空表达式
COALESCE是一个函数, (expression_1, expression_2, …,expression_n)依次参考各参数表达式,遇到非null值即停止并返回该值。如果所有的表达式都是空值,最终将返回一个空值。使用COALESCE在于大部分包含空值的表达式最终将返回空值。
返回其参数中第一个非空表达式
如果想将verfiy_date为空的选出来,通常做法:
select id from table where verify_date is null;
也可以使用如下做法,当verify_date值为空的时候,取过滤条件‘2020-09-06’代替
select id from table where coalesce(verify_date,'2020-09-06')
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?