如何订购使用UNION的SQL查询,以便按查询所在的顺序返回数据?

时间:2013-09-02 11:37:19

标签: sql oracle

我有一个SQL查询,其中包含以下几行:

SELECT R.NUMERIC_VAL, 'A'  /* query A */
  FROM TABLE_1  
 WHERE TABLE_1.DATE = TO_DATE('04/04/2012', 'DD/MM/YYYY') 
 UNION
SELECT E.NUMBER_VALUE, 'B' /* query B */
  FROM TABLE_2 
 WHERE TABLE_2.DATE = TO_DATE('05/04/2012', 'DD/MM/YYYY')
 UNION
SELECT E.OTHER_NUMBER_VALUE, 'C' /* query C */
  FROM TABLE_2
 WHERE TABLE_2.DATE = TO_DATE('05/04/2012', 'DD/MM/YYYY')
 ORDER BY 2

如您所见,我当前的解决方案取回字母A,B和C,并按第二列排序查询。我知道这个查询总是会为每个查询返回1行。我想知道是否有任何方法可以使查询按照查询当前写入的顺序恢复数据,而不必使用第二列?谢谢。

2 个答案:

答案 0 :(得分:5)

SELECT NumVal FROM
(
    SELECT R.NUMERIC_VAL AS NumVal, 1 AS queryNo
    FROM TABLE_1  
    WHERE TABLE_1.DATE = TO_DATE('04/04/2012', 'DD/MM/YYYY') 
    UNION
    SELECT E.NUMBER_VALUE AS NumVal, 2 AS queryNo
    FROM TABLE_2 
    WHERE TABLE_2.DATE = TO_DATE('05/04/2012', 'DD/MM/YYYY')
    UNION
    SELECT E.OTHER_NUMBER_VALUE AS NumVal, 3 AS queryNo
    FROM TABLE_2
    WHERE TABLE_2.DATE = TO_DATE('05/04/2012', 'DD/MM/YYYY')
) T
ORDER BY queryNo ASC

虽然没有虚假的第二列我没有看到可靠的方法,但这种方式至少它不是结果的一部分。您也可以尝试使用UNION ALL,这意味着它不必消除重复值,可能保留顺序,但正如我所说,可能不可靠。

答案 1 :(得分:5)

您必须使用order by按照您想要的顺序获取结果。当没有order by时,SQL表和SQL结果本质上是无序的,除了一些特定于数据库的异常(例如,MySQL保证使用group by时的排序)。

UNIONUNION ALL不保证结果的排序。实际上,在许多数据库中,UNION将按字母顺序(通过第一列)返回结果,作为重复删除过程的一部分。

您可以将UNION替换为UNION ALL。虽然不能保证按特定顺序返回结果,但通常会按照写入的顺序返回结果:

SELECT R.NUMERIC_VAL, 'A'  /* query A */
FROM TABLE_1  
WHERE TABLE_1.DATE = TO_DATE('04/04/2012', 'DD/MM/YYYY') 
UNION ALL
SELECT E.NUMBER_VALUE, 'B' /* query B */
FROM TABLE_2 
WHERE TABLE_2.DATE = TO_DATE('05/04/2012', 'DD/MM/YYYY')
UNION ALL
SELECT E.OTHER_NUMBER_VALUE, 'C' /* query C */
FROM TABLE_2
WHERE TABLE_2.DATE = TO_DATE('05/04/2012', 'DD/MM/YYYY')

但是,我建议你保留ORDER BY

如果您不想要第二列,请使用子查询:

select NUMERIC_VAL
from (SELECT R.NUMERIC_VAL, 'A' as ordering /* query A */
      FROM TABLE_1  
      WHERE TABLE_1.DATE = TO_DATE('04/04/2012', 'DD/MM/YYYY') 
      UNION ALL
      SELECT E.NUMBER_VALUE, 'B' /* query B */
      FROM TABLE_2 
      WHERE TABLE_2.DATE = TO_DATE('05/04/2012', 'DD/MM/YYYY')
      UNION ALL
      SELECT E.OTHER_NUMBER_VALUE, 'C' /* query C */
      FROM TABLE_2
      WHERE TABLE_2.DATE = TO_DATE('05/04/2012', 'DD/MM/YYYY')
     ) t
ORDER BY ordering;