2014-07-11 82 views
1

我有ORACLE UNION SQL工作正常。 能否請你幫我找到重寫SQL的替代品:Oracle:如何爲性能重寫UNION

SELECT * 
FROM (
    select app_id, org_id, emp_id, name, name_id, 
    from TableA AAA, TableC CCC, TableB BBB 
    where BBB.ID=CCC.ID 
    AND AAA.ID=BBB.ID 
UNION 
    select app_id, org_id, emp_id, name, name_id, 
    from TableA AAA, TableC CCC,TableD DDD 
    where DDD.ID=CCC.ID 
    AND AAA.ID=DDD.ID 
) MYTABLE 
WHERE MYTABLE.app_id = '1234' 
AND MYTABLE.org_id = '5678'; 

我試圖UNION SQL轉換成標量查詢的一些建議,但我得到的錯誤:「值過多」

SELECT 
(select app_id, org_id, emp_id, name, name_id, 
from TableA AAA, TableC CCC, TableB BBB 
where BBB.ID=CCC.ID 
and AAA.ID=BBB.ID 
and app_id = '1234' 
and org_id = '5678' 
) q1, 

(select app_id, org_id, emp_id, name, name_id, 
from TableA AAA, TableC CCC,TableD DDD 
where DDD.ID=CCC.ID 
and AAA.ID=DDD.ID 
and app_id = '1234' 
and org_id = '5678' 
) q2 
) from dual; 

我的Scalar查詢中可能存在什麼問題? 或者還有其他方法可以用更好的性能重寫此查詢嗎? 非常感謝。

+0

您不能在一列中使用子查詢中的多個值,就像你選擇的那樣。你是否嘗試過在單一選擇中對錶格D&B進行外連接? – Bob

+0

你能揭露app_id和org_id來自哪個表嗎?如果他們來自AAA和CCC,那麼您可以在加入BBB和DDD之前將其限制在子查詢中。聯盟是昂貴的,因爲它必須過濾出不同的值(而不是聯盟所有,這不關心)。如果您可以限制必須進行分組/排序的記錄數量,它將對邏輯IO數量產生巨大影響。 – Hambone

+0

如果兩個查詢都不返回重複項以過濾掉,則可以使用'union all'。 'union all'會保持原樣不變,而'union'基本上可以得到結果的所有'distinct'值,這顯然是一個額外的處理步驟。 – GolezTrol

回答

1

一開始就是在單個選擇中進行過濾。儘可能早地限制您正在使用的數據集。你現在正在做的是從表中獲取所有行,從該大數據集中獲取唯一值(你使用UNION而不是UNION ALL),過濾記錄。

select app_id, org_id, emp_id, name, name_id, 
    from TableA AAA, TableC CCC, TableB BBB 
    where BBB.ID=CCC.ID 
    AND AAA.ID=BBB.ID 
    AND app_id = '1234' 
    AND org_id = '5678' 
    UNION 
    select app_id, org_id, emp_id, name, name_id, 
    from TableA AAA, TableC CCC,TableD DDD 
    where DDD.ID=CCC.ID 
    AND AAA.ID=DDD.ID 
    AND app_id = '1234' 
    AND org_id = '5678'; 

PS您的選擇在語法上不正確。選擇列表以逗號結尾。

-1
SELECT app_id, org_id, emp_id, name, name_id 
FROM 
(
SELECT app_id, org_id, emp_id, name, name_id 
FROM TableA AAA 
JOIN TableB BBB ON AAA.ID = BBB.ID 
JOIN TableC CCC ON BBB.ID = CCC.ID 

UNION 

SELECT app_id, org_id, emp_id, name, name_id 
FROM TableA AAA 
JOIN TableC CCC ON AAA.ID = CCC.ID 
JOIN TableD DDD ON CCC.ID = DDD.ID 
) MYTABLE 

WHERE MYTABLE.app_id = '1234' 
AND 
MYTABLE.org_id = '5678'; 
+1

我不明白這與原始查詢有什麼不同,除了將where子句的連接移動到ANSI連接語法 – Hambone