【问题标题】:MySQL Union sort works unexpected at different serverMySQL联合排序在不同的服务器上意外工作
【发布时间】:2017-03-21 00:09:08
【问题描述】:

早安,

我对“简单”查询有疑问。当我在不同的服务器上执行它时,我得到了我需要的其他结果集..

我尝试通过 export->import 重新导入所有“表”,但仍然无法正常工作。

哪里有问题? MariaDB 中可能有问题吗?

数据库版本:

  • 5.6.27 - MySQL 社区服务器 (GPL),客户端:libmysql 5.0.11-dev
  • 10.0.25-MariaDB-0+deb8u1 - (Debian),客户端:libmysql 5.5.49

两者都在 MyISAM 引擎上运行。

查询:

SELECT id, datum, ordinary FROM (SELECT *, 0 as `ordinary` FROM 
    `user_todolist` WHERE `done` = '0' 
    AND `deleted` = '0' AND `id_uzivatel` = '1' ORDER BY `datum` ASC) AS a1 
UNION 
SELECT id, datum, ordinary FROM (SELECT *, 1 as `ordinary` FROM 
    `user_todolist` WHERE `done` = '1' AND `deleted` = '0' AND 
    `id_uzivatel` = '1' ORDER BY `datum` DESC) AS a2 
ORDER BY `ordinary`

结果(左侧预期,右侧无效):

SQL 解释(预期顶部,机器人无效)

【问题讨论】:

  • 为什么是ORDER BY datum ASC 然后是ORDER BY datum DESC?尝试将所有 Order By 条件分别应用于两个 select 语句,而不是整个 union select。
  • 它正在排序“任务” - 第一部分从“最近”排序,第二部分是关闭的任务,需要从“最新”排序。我试图通过一个 OrderBy 来做到这一点——但理想情况下我只需要一个问题——但两个排序都在同一列中。最终结果集按所需顺序显示在一个分页表中。

标签: mysql database union mariadb


【解决方案1】:

ORDER BY 不一定是稳定的排序。当您将ORDER BY 应用于UNION 的结果时,它可以在组内重新排序。

外部查询中不需要ORDER BY ordinary。当你使用UNION时,结果通常是按照子查询的顺序,所以第一个SELECT的结果会在前,第二个SELECT在后。

不过,您应该将 UNION 更改为 UNION ALL。默认情况下,它是UNION DISTINCT,这意味着它必须结合查询的结果来删除重复项。由于查询之间永远不会有重复(因为它们有不同的ordinary 列),这是不必要的。

另一个不依赖于此的解决方案(我实际上不确定它是否得到保证)是将ORDER BY datum 从子查询中取出,并使用主查询:

ORDER by ordinary, IF(ordinary = 0, datum, '') ASC, IF(ordinary = 1, datum, '') DESC

【讨论】:

    【解决方案2】:
    • ANSI 标准规定可以忽略子查询中的ORDER BY。这相当于说一个表对行没有内在顺序。
    • 最近Oracle 和 MariaDB(显然是独立的)都开始利用这个标准。
    • UNION ALL 是合适的,因为没有值重叠,并且由于没有重复数据删除过程,它比 UNION DISTINCT 快​​。
    • UNION传统上是通过创建一个临时表来实现的,将来自一个选择的行输入到其中,然后是下一个选择。
    • 最近在某些情况下消除了对临时表的需求。这是一个很好的优化。
    • 未来,我希望多个线程并行执行SELECTs。这将真的使您今天可能喜欢的关于事物或排序方式的任何假设失效。

    底线:移除内部ORDER BYs,添加外部ORDER BY,如@Barmar 的建议。

    这样,您的查询将在 MySQL/MariaDB 的所有过去、当前和未来版本中“正确”运行。 (几年前我第一次被这个问题所困扰:Here。)

    同时,在完全删除之前切换到 InnoDB。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-07-13
      • 2014-06-26
      • 2019-11-23
      • 2023-03-08
      • 1970-01-01
      • 2014-06-10
      • 1970-01-01
      相关资源
      最近更新 更多