2015-11-24 117 views
4

我有這樣的具有累加和要求(這是一個簡化的例子)如何重新組合嵌套選擇?

INSERT INTO DEMO (a,b,c,d,e) 
    SELECT 
    DATA.a, 
    NVL((SELECT SUM r2.x FROM EXAMPLE r2 WHERE r2.a = r1.a AND r2.i <= r1.i),0), 
    DATA.c, 
    NVL((SELECT SUM r2.y FROM EXAMPLE r2 WHERE r2.a = r1.a AND r2.i <= r1.i),0), 
    DATA.e 
    FROM 
    DATA 
    LEFT OUTER JOIN EXAMPLE r1 ON DATA.a = r1.a 

這一要求的作品,但慢得令人難以置信。由於兩個嵌套選擇看起來都一樣,我想重新組合它們。類似於

SELECT SUM r2.x, SUM r2.y FROM EXAMPLE r2 WHERE r2.a = r1.a AND r2.i <= r1.i 

但我無法成功實現此目的。我該怎麼做 ?

我都嘗試

INSERT INTO DEMO (a,c,e,b,d) 
    SELECT 
    DATA.a, 
    DATA.c, 
    DATA.e 
    (SELECT SUM r2.x, SUM r2.y FROM EXAMPLE r2 WHERE r2.a = r1.a AND r2.i <= r1.i) 
    FROM DATA 
    LEFT OUTER JOIN EXAMPLE r1 
    ON DATA.a = r1.a 

INSERT INTO DEMO (a,c,e,b,d) 
    SELECT 
    DATA.a, 
    DATA.c, 
    DATA.e 
    FROM DATA 
    LEFT OUTER JOIN EXAMPLE r1 
    ON DATA.a = r1.a 
    UNION 
    SELECT 
    (SELECT SUM r2.x, SUM r2.y FROM EXAMPLE r2 WHERE r2.a = r1.a AND r2.i <= r1.i) 
    FROM DATA 
    LEFT OUTER JOIN EXAMPLE r1 
    ON DATA.a = r1.a 
+2

一個體面的現代查詢優化器(如Oracle)將確定重新使用的表達,因此不是兩次評價它,所以我覺得你的性能問題謊言在別處。您是否檢查了執行計劃以查看查詢的每個組件的相對成本計算? – Dai

回答

3

累計總和(運行總和)自聯接的計算通常是緩慢的,因爲對於每個記錄所有匹配的前記錄必須再次被讀取。

更好地利用分析函數SUM代替:

INSERT INTO DEMO (a,b,c,d,e) 
    SELECT 
    DATA.a, 
    NVL(SUM(x) OVER (PARTITION BY r1.a ORDER BY r1.i 
         RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) , 0), 
    DATA.c, 
    NVL(SUM(y) OVER (PARTITION BY r1.a ORDER BY r1.i 
         RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) , 0), 
    DATA.e 
    FROM DATA 
    LEFT OUTER JOIN EXAMPLE r1 
    ON DATA.a = r1.a 
+0

非常感謝。我現在可以在合理的時間內運行它;) – ThomasThiebaud