前言
五个月没更新的我又回来了! 各位朋友六一快乐啊!
这次是朋友有一个比较emmm罕见的需求吧, 场景类似活动时间吧, 活动结束的倒序, 正在进行的正序, 看看sql应该怎么写
环境
Mysql版本
Mysql 5.7
准备表和数据
简单来个表, 主要就是按时间部分正序部分倒序,
CREATE TABLE `test_order` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`timer` int(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
INSERT INTO `test_order`(`id`, `timer`) VALUES (1, 10);
INSERT INTO `test_order`(`id`, `timer`) VALUES (2, 20);
INSERT INTO `test_order`(`id`, `timer`) VALUES (3, 30);
INSERT INTO `test_order`(`id`, `timer`) VALUES (4, 40);
想实现的是 timer <= 20 asc, timer >20 desc, 预期结果 10, 20, 40, 30
实现方案
两种实现方法思路都是一样的
实现方案一(Case)
SELECT *, CASE WHEN timer > 20 THEN
2 ELSE 1
END AS group_id,
CASE
WHEN timer > 20 THEN
timer * ( - 1 ) ELSE timer
END AS sort
FROM
test_order
ORDER BY
group_id ASC,
sort ASC;
简单说一下实现方式, 就是先按照 >20 和 <=20 给一个强排(1 > 2), 然后在对 >20的乘个-1, 改变正排序, 结果符合预期
实现方案二(If)
SELECT * FROM test_order ORDER BY IF ( timer > 20,
0,
1
) DESC,
IF
( timer <= 20, timer, timer *- 1 ) ASC;
其他未实现方案
多条件排序
SELECT * FROM test_order ORDER BY timer>20 ASC, timer<=20 ASC; // 10, 20, 30, 40
SELECT * FROM test_order ORDER BY timer>20 ASC, timer<=20 DESC; // 10, 20, 30, 40
SELECT * FROM test_order ORDER BY timer>20 DESC, timer<=20 ASC; // 30, 40, 10, 20
SELECT * FROM test_order ORDER BY timer>20 DESC, timer<=20 DESC; // 30, 40, 10, 20
这是因为 order 判断结果为1和0, 然后默认按id排序, 把id=3改成5, 结果就是
union
先直接拼两条语句
SELECT
*
FROM
test_order
WHERE
timer < 20 ORDER BY timer ASC UNION SELECT * FROM test_order WHERE timer >= 20
ORDER BY
timer DESC;
报错 1221 - Incorrect usage of UNION and ORDER BY
; 加别名解决
SELECT
*
FROM
( SELECT * FROM test_order WHERE timer < 20 ORDER BY timer ASC ) AS one UNION ALL
SELECT
*
FROM
( SELECT * FROM test_order WHERE timer >= 20 ORDER BY timer DESC ) AS two;
子句的order没有生效, 看下官方文档
子句必须要配合limit才可以使用order, 但这样就没办法分页了…放弃