简介:MySQL排序ORDER BY详解
在前面的文章中我们讲解了MySQL安装,分布式部署及MySQL锁测试等,今天我们来讲讲MySQL排序吧。
ORDER BY排序分为静态排序和动态排序两种。所谓静态排序就是排序的字段不变,而静态排序则是根据所查字段的结果动态进行排序。
ORDER BY语法
SELECT * FROM table ORDER BY column1 ASC/DESC,column2 ASC/DESC;
column1:代表排序字段一
column2:代表排序字段二
AES:排序方式,升序(从小到大排序,默认为:升序)
DESC:排序方式,降序(从大到小)
实践准备
//创建测试表
CREATE TABLE `pay_logs` (
`id` int UNSIGNED primary key auto_increment,
`uid` int UNSIGNED NOT NULL DEFAULT '0' COMMENT '用户id',
`order_id` int UNSIGNED NOT NULL DEFAULT '0' COMMENT '订单id',
`out_trade_no` char(24) UNIQUE COMMENT '商户订单号',
`transaction_id` char(32) DEFAULT NULL COMMENT '微信支付订单号',
`business_type` tinyint UNSIGNED NOT NULL DEFAULT '0' COMMENT '0商品支付,1充值',
`pay_money` decimal(8,2) NOT NULL DEFAULT '0.00' COMMENT '支付金额',
`status` tinyint UNSIGNED NOT NULL DEFAULT '0' COMMENT '0未支付,1已支付,2支付取消或失败',
`add_time` int UNSIGNED NOT NULL DEFAULT '0' COMMENT '下单时间',
`update_time` int UNSIGNED NOT NULL DEFAULT '0' COMMENT '最后更新时间',
`pay_time` int UNSIGNED NOT NULL DEFAULT '0' COMMENT '支付时间'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COMMENT='支付记录';
//添加测试数据
INSERT INTO `pay_logs` (`id`, `uid`, `other_id`, `out_trade_no`, `transaction_id`, `business_type`, `pay_money`, `status`, `add_time`, `pay_time`) VALUES
(1, 1, 1, '165020201028181710386397', NULL, 4, '5.00', 0, 1603880230, 0),
(2, 45, 1, '857120201028182936852971', NULL, 4, '5.00', 0, 1603880976, 0),
(3, 5, 1, '747720201028185318447333', NULL, 4, '5.00', 0, 1603882398, 0),
(4, 5, 1, '185420201028191234208651', NULL, 4, '5.00', 0, 1603883554, 0),
(5, 110, 22, '502020201110201234101100', NULL, 1, '1.00', 0, 1605010354, 0),
(6, 132, 26, '339820201112000050636975', '4200000827202011127847144088', 3, '1.00', 1, 1605110451, 1605110463),
(7, 132, 26, '512420201112000203402943', NULL, 1, '1.00', 0, 1605110523, 0),
(8, 132, 26, '365020201112222940382225', NULL, 1, '1.00', 0, 1605191381, 0),
(9, 160, 28, '255320201113161037639377', NULL, 1, '1.00', 0, 1605255037, 0),
(10, 301, 41, '189920201123143342552993', NULL, 3, '1.00', 0, 1606113223, 0),
(11, 351, 48, '973320201202174842934436', NULL, 1, '1.00', 0, 1606902522, 0),
(12, 351, 48, '224320201202174844632776', NULL, 1, '1.00', 0, 1606902524, 0),
(13, 364, 1, '103120201202220020354618', '4200000844202012022311011882', 4, '5.00', 1, 1606917621, 1606917627),
(14, 364, 49, '961420201202220354317164', NULL, 1, '1.00', 0, 1606917835, 0),
(15, 364, 52, '310620201203000920377865', NULL, 1, '1.00', 0, 1606925360, 0),
(16, 1, 31, '443320201203094302166248', NULL, 1, '1.00', 0, 1606959783, 0),
(17, 369, 53, '394520201203142937787909', NULL, 3, '100000.00', 0, 1606976977, 0),
(18, 415, 57, '903720201210001320521151', '4200000822202012100679251657', 3, '1.00', 1, 1607530400, 1607530406),
(19, 1, 1, '121620210715153532867102', NULL, 0, '5000.00', 0, 1626334532, 0),
(20, 795, 2, '415220210726143120854840', NULL, 0, '0.10', 0, 1627281080, 0),
(26, 795, 2, '643820210726143852187491', NULL, 0, '0.10', 0, 1627281532, 0),
(27, 795, 2, '650020210726143854649248', '4200001187202107263633873051', 0, '0.10', 1, 1627281534, 1627281762),
(28, 795, 3, '789620210726145832984362', '4200001150202107262938135862', 0, '0.10', 1, 1627282712, 1627282720),
(29, 1, 4, '728520210729155324726495', NULL, 0, '18.00', 0, 1627545204, 0),
(30, 1, 5, '627420210814165714878311', NULL, 0, '18.00', 0, 1628931434, 0);
静态排序
前面已经说过静态排序就是ORDER BY后面排序的字段固定不变,如下所示:
SELECT * FROM pay_logs ORDER BY id;
上述SQL语句中用于排序的字段固定的,这就是静态排序。
当然ORDER BY后面还可以添加其他的字段进行排序,如下所示:
SELECT * FROM pay_logs ORDER BY id DESC,status ASC;
ORDER BY排序优先根据第一个字段进行排序,再根据第二个字段排序,依次进行。
注意:多个字段排序时,如果第一个排序的字段的值是唯一的,不重复的,后面的排序字段将失效。
比如上面的SQL中id是唯一的,status字段的排序就没有作用了。
动态排序
所谓动态排序就是ORDER BY后面的排序自动会根据值的变化而变化。例如:在status=1的时候根据字段B排序,status=2的时候根据字段C排序。一般动态排序会搭配条件判断语句进行。比如:case when 和 if 等。
我们先来看看这个SQL
SELECT * FROM `pay_logs`
ORDER BY `status` DESC,
CASE WHEN `status`=0 THEN `add_time` END DESC ,
CASE WHEN `status`=1 THEN `pay_time` END DESC;
执行结果如下:
在这个SQL中优先根据支付状态(status)进行排序,status相同时再根据status的值判断,status=0时根据add_time字段排序,status=1时根据支付时间(pay_time)排序,这就是case when动态排序案例。
if动态排序和case when类似,也是对字段的值进行判断,再给出排序方式。SQL语句如下所示:
SELECT * FROM `pay_logs`
ORDER BY `status` DESC,
IF (`status`=0,0,1), `add_time` DESC,`pay_time` DESC;
if条件语句可分为两部分,status=0时返回0,此时排序按add_time字段倒序,否则返回1,排序按pay_time字段排序。
请大家注意:IF SQL语句中逗号及返回值的顺序
上述SQL中订单status=0订单没有支付也就没有支付时间,所以未支付订单按创建时间排序,已支付按支付时间排序,执行结果如下所示:
ORDER BY为什么支持动态排序?主要是因为ORDER BY执行顺序优先级比较低,它实在获取到结果集之后才进行排序。当然在获取结果集之后我们还可以搭配函数或者其他的条件使用,比如:LIKE、IN、CONCAT等。
总结:
有遗漏或者不对的可以在我的公众号留言哦