2016-08-08 35 views
1

SELECT語句中使用語句如何保證執行順序? 例如:ORACLE SQL如何實現UNION子句,但維護每個SELECT的順序

SELECT a.poclcdde, a.poclnpol, a.poclcdcl 
    FROM dtpocl a 
WHERE  a.poclcdcl IN (216450, 
          562223, 
          250056, 
          202153, 
          8078) 
     AND POCLCDCE = 0 
     AND POCLTPSG = '01' 
UNION 
SELECT a.poclcdde, a.poclnpol, a.poclcdcl 
    FROM dtpocl a 
WHERE  a.poclcdcl IN (216450, 
          562223, 
          250056, 
          202153, 
          8078) 
     AND POCLTPSG = '02' 

POCLCDDE POCLNPOL POCLCDCL 
---------- ---------- ---------- 
     100 1000001  202153 
     100 5001021  216450 
     100 9000386  8078 
     100 9900633  250056 
     100 9900634  250056 
     100 9901720  562223 
     100 9901763  562223 
     200 1000001  202153 
     200 5001021  216450 

在這種情況下,我怎麼能保證第一個記錄是從QUERY1,其餘來自QUERY2。 我可以使用poclcdcl列(或虛擬列),然後按順序,但在這種情況下,我需要得到DISTINCT行。

SELECT * 
    FROM (SELECT a.poclcdde, 
       a.poclnpol, 
       a.poclcdcl, 
       1 AS TYPE 
      FROM dtpocl a 
      WHERE  a.poclcdcl IN (216450, 
            562223, 
            250056, 
            202153, 
            8078) 
       AND POCLCDCE = 0 
       AND POCLTPSG = '01' 
      UNION 
      SELECT a.poclcdde, 
       a.poclnpol, 
       a.poclcdcl, 
       2 AS TYPE 
      FROM dtpocl a 
      WHERE  a.poclcdcl IN (216450, 
            562223, 
            250056, 
            202153, 
            8078) 
       AND POCLTPSG = '02') 
ORDER BY TYPE 


    POCLCDDE POCLNPOL POCLCDCL  TYPE 
---------- ---------- ---------- ---------- 
     200 1000001  202153   1 
     100 1000001  202153   1 
     100 9000386  8078   1 
     100 9900634  250056   2 
     100 9901720  562223   2 
     100 9901763  562223   2 
     200 5001021  216450   2 
     100 9000386  8078   2 
     100 5001021  216450   2 
     100 9900633  250056   2 

我需要這個按順序交互每一行:第一個查詢優先。 感謝

+1

你不能,因爲UNION刪除重複。 – jarlh

+0

好的...並且不使用UNION?有什麼辦法嗎? – milheiros

+1

你可以做UNION ALL。先選擇'1',然後選擇'2'。按該欄排序。 – jarlh

回答

1

您可以使用union alltype「虛擬」欄目,以獲得正確的順序,並在row_number解析函數的返回值使用過濾器刪除重複的,而優先第一次查詢的行:

with cte as (
      SELECT a.poclcdde, 
       a.poclnpol, 
       a.poclcdcl, 
       1 AS TYPE 
      FROM dtpocl a 
      WHERE  a.poclcdcl IN (216450, 
            562223, 
            250056, 
            202153, 
            8078) 
       AND POCLCDCE = 0 
       AND POCLTPSG = '01' 
      UNION ALL 
      SELECT a.poclcdde, 
       a.poclnpol, 
       a.poclcdcl, 
       2 AS TYPE 
      FROM dtpocl a 
      WHERE  a.poclcdcl IN (216450, 
            562223, 
            250056, 
            202153, 
            8078) 
       AND POCLTPSG = '02' 
) 
select poclcdde, poclnpol, poclcdcl 
    from (select t.*, 
       row_number() over (
       partition by t.poclcdde, t.poclnpol, t.poclcdcl 
        order by t.type) as rn 
      from cte t) 
where rn = 1 
order by type 
+0

謝謝@sstan。我得到一個「虛擬」行命令。但我怎麼能確認這一點? 'UNION ALL'是否返回一個隨機的行順序? – milheiros

+0

是的,但這就是爲什麼我在外部查詢中具有'ORDER BY type'子句,以確保第一個查詢中的行總是出現在第二個查詢的*行之前。那是你在找的東西,對吧? – sstan

3

你可以這樣做:

SELECT * 
    FROM (SELECT a.poclcdde, 
       a.poclnpol, 
       a.poclcdcl, 
       1 AS TYPE 
      FROM dtpocl a 
     WHERE  a.poclcdcl IN (216450, 
            562223, 
            250056, 
            202153, 
            8078) 
       AND POCLCDCE = 0 
       AND POCLTPSG = '01' 
     UNION 
     SELECT a.poclcdde, 
       a.poclnpol, 
       a.poclcdcl, 
       2 AS TYPE 
      FROM dtpocl a 
     WHERE  a.poclcdcl IN (216450, 
            562223, 
            250056, 
            202153, 
            8078) 
       AND POCLTPSG = '02' 
       AND NOT EXISTS (SELECT NULL 
           FROM dtpocl a 
           WHERE  a.poclcdcl IN (216450, 
                 562223, 
                 250056, 
                 202153, 
                 8078) 
            AND POCLCDCE = 0 
            AND POCLTPSG = '01') 
       ) 
ORDER BY TYPE 
+0

謝謝@Tony。它的工作原理,這是我記得的其他解決方案之一。但是'UNION'可以保證訂單嗎?因爲這 - http://stackoverflow.com/questions/15766359/does-union-all-guarantee-the-order-of-the-result-set - ,我不這麼認爲。 – milheiros

+2

不,您需要在ORDER BY子句中指定所需的任何順序。這適用於任何查詢! –

3

您是來自同一個表中選擇相同的列,所以你不需要兩個查詢,但只是一個與Appro公司priate WHERE條款。在你的情況下,ORDER BY條款很簡單;在更復雜的情況下,您可以使用ORDER BY中的CASE WHEN表達式。

select poclcdde, poclnpol, poclcdcl 
from dtpocl 
where poclcdcl in (216450, 562223, 250056, 202153, 8078) 
and 
(
    (pocltpsg = '01' and poclcdce = 0) 
    or 
    pocltpsg = '02' 
) 
order by pocltpsg; 

UPDATE:你說你得到重複,但一旦你使用DISTINCT,你不能用pocltpsg進行排序。這是真的,對於poclcdde, poclnpol, poclcdcl的一個組合,您可能有pocltpsg ='01'和'02'的記錄。因此,您必須按poclcdde, poclnpol, poclcdcl進行彙總,並決定是否按min(pocltpsg)max(pocltpsg)(或任何其他彙總)進行排序。

select poclcdde, poclnpol, poclcdcl 
from dtpocl 
where poclcdcl in (216450, 562223, 250056, 202153, 8078) 
and 
(
    (pocltpsg = '01' and poclcdce = 0) 
    or 
    pocltpsg = '02' 
) 
group by poclcdde, poclnpol, poclcdcl 
order by min(pocltpsg); 
+0

此解決方案不會刪除重複項。放置'DISTINCT',避免使用'ORDER BY' – milheiros

+2

其實@Thorsten是對的。因爲你的2個查詢過濾了'pcltpsg',但期望值不同,所以重複甚至不可能開始。 – sstan

+1

我已更新我的查詢以顯示如何處理重複項。 –