2013-02-21 24 views
0

我想知道如何在不必寫出(或使數據庫進程)這個查詢的主要部分兩次的情況下執行此操作。使用相同的數據更高效地創建Oracle UNION查詢

我的情況是我在查詢Oracle企業數據庫(我受DBA限制,所以有些解決方案可能無法正常工作,但我不確定我在什麼程度上受到限制,直到我嘗試並且不知道該去哪裏)。

目前,我的查詢如下所示:

SELECT 
     a.Field1, 
     a.Field2, 
     b.Field3, 
     b.Field4, 
     c.Field5 
    FROM 
     a, 
     b, 
     c, 
    WHERE 
      a.FieldX = b.FieldX 
     AND 
      b.FieldY = c.FieldY 

UNION 
    (
    SELECT 
     d.Field6 as Field1, 
     d.Field7 + d.Field8 as Field2, 
     MainQuery.Field3, 
     MainQuery.Field4, 
     MainQuery.Field5 
    FROM 
     (
      SELECT 
       a.Field1, 
       a.Field2, 
       b.Field3, 
       b.Field4, 
       c.Field5 
      FROM 
       a, 
       b, 
       c, 
      WHERE 
        a.FieldX = b.FieldX 
       AND 
        b.FieldY = c.FieldY 
       AND 
        a.FieldZ = 'XXXX' 
     ) MainQuery, 

     d 
    WHERE 
     MainQuery.Field1 = d.Field6 
) 

簡單地說,我有一個主查詢(第一部分),返回我的結果的大部分,然後我重複與主查詢額外限制(a.FieldZ = 'XXXX'),並從此查詢中提取數據,並使用UNION將第二個表格附加到主查詢中。

我面臨的主要挑戰是Field1 & Field2的定義在2個查詢之間發生了變化,所以我無法弄清楚如何進行簡單的連接。但是我相信必須有一種方法可以實現這一點,而不必讓數據庫查詢兩次相同的數據。

有關如何使此查詢更高效的任何想法?

謝謝!


基於註釋,解釋多一點關於這個查詢 - 我所試圖做的就是我的整個數據unvierse查詢上半年,然後在第二個上多餘的行追加查詢的記錄的一半,其中a.FieldZ = 'XXXX'其中計算是Field1Field2

+0

請問您可以發表表格定義嗎? – twoleggedhorse 2013-02-21 14:52:05

+0

你能用這個查詢解釋你在現實世界中想要做什麼嗎? – 2013-02-21 14:53:13

+0

首先,你的僞查詢是錯誤的(選擇field6,而你只在子查詢中選擇5)。接下來,如果我理解正確,您希望FieldA具有不同的值,具體取決於FieldZ是否爲XXX。有更好的解決方案可以做到這一點(例如'DECODE') – Najzero 2013-02-21 14:54:26

回答

2

所以,下面您的意見,您的要求似乎是「第2列是從表M服用。Additionaly,當M.fieldZ = 'XXX'一個額外的行同場從表需要D需要添加。」

在這種情況下,您將不得不使用UNION ALL或通過連接到2行表來複制記錄。您可以使用WITH子句在SELECT中重用子查詢。這會使其更具可讀性,並且優化器可能決定只運行一次查詢(通過將子查詢的結果保存在temp中)。

WITH mainquery AS (SELECT /* your main query */) 
SELECT * 
    FROM mainquery 
UNION ALL 
SELECT field1, d.field2 /*, ... */ 
    FROM (SELECT * FROM mainquery WHERE fieldZ = 'XXX') m 
    JOIN d ON m.field1 = d.field6 
+0

謝謝,但我認爲這是我提到保羅的同樣的問題 - 因爲我需要數據兩種方式時FieldZ ='XXXX',這並不給我因爲Case語句只會給我查詢結果的後半部分。沒有? – 2013-02-21 15:20:38

+0

你說得對,如果fieldZ ='XXX'',我的查詢不會返回兩條記錄。我認爲你將不得不使用UNION(你可能想要使用UNION ALL),或者通過連接到2行表(這可能導致相同的計劃)來重複行。看到我更新的答案。 – 2013-02-21 15:56:01

0

略有不同使用case聲明(http://www.techonthenet.com/oracle/functions/case.php

select case when FieldZ = 'XXXX' then Field6 else Field1 end as Field1, 
     case when FieldZ = 'XXXX' then Field7 + Field8 else Field2 as Field2, 
     Field3, 
     Field4, 
     Field5 
from a join b on a.FieldX = b.FieldX 
     join c on b.FieldY = c.FieldY 
     left join d on a.Field1 = d.Field6 
+0

謝謝你的代碼,但是這並不能真正解決問題,因爲我需要數據**兩種方式,當'FieldZ ='XXXX''where case'聲明只會給我的後半部分查詢的結果。沒有?? – 2013-02-21 15:03:52

+0

是的。數據在哪裏?申請,報告或其他地方? – paul 2013-02-21 15:17:52

+0

一份報告 - 基本上加載到一張Excel表格 – 2013-02-21 15:18:52

0

如果你的目的是複製的XXXX的記錄,那麼你就可以簡化查詢到合適的加盟與case語句:

SELECT (case when a.FieldZ = 'XXXX' then a.Field1 else d.Field6 end) as Field1, 
     (case when a.FieldZ = 'XXXX' then a.Field2 else d.Field7 + d.Field8 end) as Field2, 
     b.Field3, 
     b.Field4, 
     c.Field5 
FROM a join 
    b 
    on a.FieldX = b.FieldX join 
    C 
    on b.FieldY = c.FieldY left outer join 
    d 
    on A.Field1 = d.Field6 and 
     a.FieldZ = 'XXXX' 

如果要複製這些記錄,然後一些似乎是必要的union all

1

以下是我相信給你所需答案的方法。如果沒有大量數據,我無法判斷它是否會更快。在這裏,您將掃描臨時表幾次,但如果基本查詢從表a,b,c和d返回一小部分數據,則這可能會少一些工作。

with foo as 
    (SELECT 
     a.Field1, 
     a.Field2, 
     a.FieldZ, 
     b.Field3, 
     b.Field4, 
     c.Field5 
    FROM 
     a, 
     b, 
     c 
    WHERE 
      a.FieldX = b.FieldX 
     AND 
      b.FieldY = c.FieldY 
) 
select Field1 
     ,field2 
     ,field3 
     ,field4 
     ,field5 
from foo 
union 
select 
d.Field6 as Field1 
,d.Field7 ||'+'|| d.Field8 as Field2 
,foo.Field3 
,foo.Field4 
,foo.Field5 
from foo 
join d on foo.field1 = d.field6 
where foo.fieldz = 'XXXX' 
+0

謝謝@ jwhite9 - 這就是我最終這樣做的方式。接受文森特的答覆,因爲他更早發佈了答案。謝謝你和你的幫助! – 2013-02-21 18:47:40