2016-08-08 22 views
1

ステートメントでUNION句を使用する方法実行順序をどのように保証できますか?たとえば :この場合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

OK ... UNIONを使わずに?何か方法はありますか? – milheiros

+1

UNION ALLを実行できます。最初の選択に「1」を追加し、2番目に「2」を追加します。その列で注文する。 – jarlh

答えて

1

をあなたは正しい順序を取得し、へrow_number解析関数の戻り値にフィルタを使用するtype「仮想」欄でunion allを使用することができます最初のクエリの行を優先しながら、重複を削除:

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

はい、しかし、それは、第1クエリの行が第2クエリの*行より前に常に現れることを保証するために、外部クエリに '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

Thanks @Tony。それは動作し、それは私が覚えている他の解決策の1つでした。しかし、「UNION」は注文を保つことが保証できますか?このように - http://stackoverflow.com/questions/15766359/does-union-all-guarantee-the-order-of-the-result-set-、私はそうは思わない。 – milheiros

+2

いいえ、ORDER BY句で必要な順序を指定する必要があります。それはどんなクエリにも当てはまります! –

3

あなたが同じテーブルから同じ列を選択しているので、あなたは、2つのクエリを必要としませんが、ちょうどアプロと1プライス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

重複を処理する方法を示すためにクエリを更新しました。 –

関連する問題