2014-07-11 48 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