2012-12-13 21 views
0

我正在使用Oracle 11g。如何在Oracle中創建一個高效的UNION?

我有2個相關的表:存儲的值(A)和插入的新值(B)。兩者之間的相關性爲3列(客戶,組和個人代碼)。每個表格都有大約20個其他列(讓我們稱它們爲屬性)。

我必須匹配它們,以便我可以知道哪些值是新的(id爲B,而不是A),因此我將它們插入到A中,它們是等號(B中的ID和A中的屬性相同),以及不在新值中(A中的id,而不是B中的),所以我從存儲的值(A)中刪除它們。

例如:

 
A: 

client | group | personcode | name | surname 
_________________________________________________ 
1  | 1  | 1    | joe | doe 
1  | 1  | 2    | carl | john 
1  | 1  | 3    | john | john 

B:

 
client | group | personcode | name | surname 
_________________________________________________ 
1  | 1  | 1    | joe | doe 
1  | 1  | 3    | john | john 
1  | 1  | 4    | mary | con 

在這個例子中,人4是新的,人2應刪除1和3保持相同。

所以,我需要一個查詢返回的結果如下:

 
client | group | personcode | action 
_________________________________________ 
1  | 1  | 1    | equal 
1  | 1  | 2    | remove 
1  | 1  | 3    | equal 
1  | 1  | 4    | new 

我所做的是以下查詢:

WITH 
    A AS (
    -- select from A table 
    ), 
    B AS 
    (
     -- select from B table 
    ),  
    delete AS 
    (
    -- select from A WHERE NOT EXISTS (B.id = A.ID) 
    ),  
    news AS 
    (
    -- select from B WHERE NOT EXISTS (A.id = B.ID) 
    ), 
    eq AS 
    (
    -- select A.* from A, B WHERE A.id = B.id AND A.attributes = B.attributes 
    ) 
    select action.client, action.group, action.personcode, 'remove' from delete action 
    UNION ALL 
    select action.client, action.group, action.personcode, 'new' from news action 
    UNION ALL 
    select action.client, action.group, action.personcode, 'equal' from eq action 
    ; 

的問題是,雖然每個那些3當我使用UNIONUNION ALL合併它們時,持續選擇運行時間少於10秒,完整查詢持續約90秒,即使刪除或新或等於空也是如此。它可能在A或B中超過3000行。

是否有任何方法以更好,更快的方式獲得此結果?

+0

找到罪惡的另一個線索......在刪除,新聞和eq的內部查詢中,我正在篩選client =?和group =?,所以我得到這個客戶的這個組的人。當我刪除這個過濾器時,這個查詢不像以前那樣在10秒內運行。刪除一個需要50秒,消息不到1秒,現在需要6秒。 – Goyo

+0

好吧,另一個線索:如果我在A和B查詢中插入此ID過濾器,那麼完整查詢只需要12秒,因爲它只是考慮這個ID的行。問題是這是查看使用的查詢,所以我不能把這個ID由參數,我可以嗎? – Goyo

+1

對於有效的聯合,不要使用oracle。使用高效的牧師! – Moshe

回答

0

好的,謝謝大家的回覆。 我終於做了一個視圖,我通過一些參數來過濾前兩個查詢,使用this blog 中描述的策略現在完成的過程持續30秒,如果在A或B沒有行(在之前,它總是持續90秒)。 這是對我的當前程序影響較小的解決方案。

2

如果表B具有所需的數據,爲什麼不使用該表而不是表A中的數據?創建一個同義詞,指向具有正確數據的同義詞並引用它。

+0

表B和A具有不同的值。起初,A是空的。在一些進程之後,一些行被插入到B中。這些是應該存儲在A中的新行。在一些進程再次運行後,A和B應該被合併(B中的新行應該被插入到A中,並且在A中而不是在B中的行應該被刪除) – Goyo

+0

I undertsand that。但是你對這個過程所做的似乎是通過插入,更新和刪除來使表A中的數據與表B中的數據相同。因此,如果表A中的數據與此過程結束時表B​​中的數據相匹配,那麼您可以僅對A進行分隔並從B重新加載,或者執行分區交換來交換數據,或者只需重新指定需要數據通過同義詞到表B. –

+0

是的,我的解釋並不完全準確。你是對的,如果這是我想要做的,截斷B到A應該是一個解決方案。但是,刪除/插入行時必須執行的操作是通知其他應用程序該人員應該被刪除/插入,並根據更改生成XML,而不僅僅是刪除/插入本身。 – Goyo

4

您可以外部連接表格以生成它們之間差異的日誌。

select coalesce(a.id,b.id) id, 
     case when a.id is null 
       then 'new' 
      when b.id is null 
       then 'remove' 
      when a.col1 = b.col1 and a.col2 = b.col2 ... 
       then 'same' 
      else 'different' 
     end 
from a full outer join b on (a.id = b.id) 
+1

如果col1爲NULLABLE,請使用WHEN(a.col1 = b.col1)OR(a.col1 IS NULL AND b.col1 IS NULL)... –

相關問題