Mysql

关注公众号 jb51net

关闭
首页 > 数据库 > Mysql > MySQL UNION和ORDER BY混用问题

踩坑MySQL UNION和ORDER BY混用的问题及解决

作者:咖啡Beans

MySQL中UNION合并多个子集时,内部ORDER BY可能失效,解决方法:各子集添加LIMIT,外层再包裹SELECT并使用ORDER BY,确保整体排序正确

摘要

本文介绍MySQL中使用union多个子集导致排序失效的场景如何解决。

失效场景复现

目的

想先让A表按id升序,再让B表按id降序,然后拼在一起,最终想保证顺序一致

(SELECT id, name FROM A ORDER BY id ASC)
UNION
(SELECT id, name FROM B ORDER BY id DESC);

结果

A或B内单独查询顺序无误,但UNION后排序反而乱了…

原因

mysql8.0官方给的解释是:UNION分支里的ORDER BY会被优化器直接扔掉,想让单个分支先排好序,必须在该分支里再加一个LIMIT任意大数,并且最后把整个UNION再包一层SELECT,在最外层写ORDER BY。

正确写法

SELECT * FROM (
  SELECT id, name, 1 AS seq    -- 用常量列保住先后顺序
  FROM A
  ORDER BY id ASC
  LIMIT 99999999    -- 必须加LIMIT,否则ORDER BY会被优化掉
) a
UNION
SELECT * FROM (
  SELECT id, name, 2 AS seq
  FROM B
  ORDER BY id DESC
  LIMIT 99999999
) b
ORDER BY seq, id;    -- 外层再按需要整体排序
SELECT * FROM (
  SELECT id, create_time, 1 AS seq    -- 用常量列保住先后顺序
  FROM table_A
  ORDER BY create_time ASC
  LIMIT 99999999    -- 必须加LIMIT,否则ORDER BY会被优化掉
) a
UNION
(
  SELECT id, create_time, 2 AS seq
  FROM table_B
  ORDER BY id DESC
  LIMIT 99999999
) b
ORDER BY seq;    -- 仅保证先A后B,不再对内部二次排序

总结

以上我们了解了mysql中union多个子集时防止子集内的排序失效的做法,子集写limit,外层再包含,最终再order。

这些仅为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文