union all in SQL (Postgres) 乱序

union all in SQL (Postgres) mess the order

我有一个按日期排序的查询,有一个查询我对其进行了一些简化,但基本上是:

select * from 
(select  start_date, to_char(end_date,'YYYY-mm-dd') as end_date from date_table
order by start_date ,end_date ) 
where start_date is null or end_date is null

显示完美顺序

但我补充

union all
select start_date, 'single missing day' as end_date  from 
calendar_dates
where db_date>'2017-12-12' and db_date<'2018-05-13'     

然后整个秩序就乱套了。为什么会这样? Union 或 union all 应该只是将第一个查询的数据集附加到第二个查询,对吗?它不应该在第一个查询中弄乱顺序,对吗?

我知道这个查询没有任何意义,但我已将其简化为 显示语法。

你错了。此查询:

select d.*
from (select start_date, to_char(end_date,'YYYY-mm-dd') as end_date
      from date_table
      order by start_date, end_date
     ) d
where start_date is null or end_date is null

没有"show perfect order"。我可能只是碰巧产生了你想要的顺序,但这是巧合。 获得特定顺序结果的唯一方法是在最外面的 SELECT. 句点中使用 ORDER BY

因此,如果您想要特定顺序的结果,请使用 order by:

select d.*
from ((select d.start_date, to_char(end_date, 'YYYY-mm-dd') as end_date, 1 as ord
       from date_table d
       where d.start_date is null or d.end_date is null
       order by start_date, end_date
      ) union all
      (select cd.start_date, 'single missing day' as end_date, 2 as ord
       from calendar_dates cd
       where cd.db_date > '2017-12-12' and cd.db_date < '2018-05-13' 
      )
     ) d
order by ord, start_date;

您无法通过假设 UNION ALL 将按照您编写的顺序 附加 查询来预测顺序结果。

查询规划器 将按照它认为合适的顺序执行您的查询。这就是为什么你有 ORDER BY 条款。使用它!

例如,如果您想强制第一个查询的顺序,然后是第二个查询,请执行:

select * from 
(select  1, start_date, to_char(end_date,'YYYY-mm-dd') as end_date from date_table
order by start_date ,end_date ) 
where start_date is null or end_date is null
union all
select 2, start_date, 'single missing day' as end_date  from 
calendar_dates
where db_date>'2017-12-12' and db_date<'2018-05-13' 
ORDER BY 1

UNION 或 UNION ALL 会打乱第一个 SELECT 的顺序。因此,我们可以做一个技巧,我们将 re-order 这些列在外部 Select 中,如下所示:

SELECT * FROM 
( 
     select colA, colB
          From TableA
          -- ORDER BY colA, colB --   
     UNION ALL   
     select colC, colD
         FROM TableB
         ORDER BY colC, colD 
) tb 
ORDER BY colA, colB