使用“Union distinct”构造时保留子查询中的记录顺序

时间:2011-09-26 19:15:51

标签: mysql sql-order-by union

我想确保在使用Union distinct时保留子查询的结果顺序。请注意,在进行联合时,需要使用“union distinct”来过滤重复项。

例如:

select columnA1, columnA2 from tableA order by [columnA3] asc
union distinct
select columnB1, columnB2 from tableB

当我运行此操作时,我希望从子查询(从columnA1中选择columnA2tableA排序[columnA3] asc)排序的记录首先出现(如由columnA3 asc)按顺序返回,后跟tableB

我假设我不能添加另一个虚拟列,因为这会使联合变得不起作用。所以,这不起作用:

select column1, column2 from 
 ( select column1, column2, 1 as ORD from tableA order by [columnA3] asc
 union distinct
 select column1, column2, 2 as ORD from tableB 
 ) order by ORD

2 个答案:

答案 0 :(得分:4)

基本上,MySQL在使用“Union distinct”构造时不会保留子查询中的记录顺序。经过一些研究,我发现如果我们放入一个限制子句或嵌套查询它就可以了。所以,下面是两种方法:

方法-1:使用限制条款

         select columnA1, columnA2 from tableA order by [columnA3] asc Limit 100000000
         union distinct
         select columnB1, columnB2 from tableB

我使用少量数据集测试了这种行为,它似乎一致地工作。此外,MySQL的文档(http://dev.mysql.com/doc/refman/5.1/en/union.html)中提到了这种行为:  “对各个SELECT语句使用ORDER BY并不意味着行在最终结果中出现的顺序,因为UNION默认生成一组无序行。因此,在此上下文中使用ORDER BY通常与LIMIT结合使用,因此它用于确定要为SELECT检索的所选行的子集,即使它不一定影响这些行的顺序。最终的UNION结果。如果在SELECT中没有LIMIT出现ORDER BY,它会被优化掉,因为它无论如何都没有效果。“

请注意,选择LIMIT为10000000000没有特别的理由,除了有足够高的数字以确保我们涵盖所有案件。

方法-2:如下所示的嵌套查询也可以。

        select column1, column2 from 
        ( select column1, column2 order by [columnA3] asc ) alias1
        union distinct
        ( select column1, column2 from tableB )

我找不到嵌套查询工作的原因。网上有一些参考文献(例如来自Phil McCarley的http://dev.mysql.com/doc/refman/5.0/en/union.html),但没有来自MySQL的官方文档。

答案 1 :(得分:1)

select column1, column2 from 
 ( select column1, column2, 1 as ORD from tableA
 union distinct
 select tableB.column1, tableB.column2, 2 as ORD from tableB 
  LEFT JOIN tableA
      ON tableA.column1 = tableB.column1 AND tableA.column2 = tableB.column2
  WHERE tableA.column1 IS NULL
 ) order by ORD

请注意,UNION不仅可以在不同的集合中进行重复数据删除,而且还可以在集合

中进行重复数据删除

可替换地:

select column1, column2 from 
 ( select column1, column2, 1 as ORD from tableA
 union distinct
 select column1, column2, 2 as ORD from tableB 
 WHERE (column1, column2) NOT IN (SELECT column1, column2 from tableA)
 ) order by ORD