Sql 查询优化-联合
我使用下面的查询从SOURCE1、SOURCE2、SOURCE3三个表中获取数据,这些数据需要插入到另一个表FINAL中。我想知道下面的查询是否可以进一步优化Sql 查询优化-联合,sql,performance,union,Sql,Performance,Union,我使用下面的查询从SOURCE1、SOURCE2、SOURCE3三个表中获取数据,这些数据需要插入到另一个表FINAL中。我想知道下面的查询是否可以进一步优化 SELECT s3.unit ,s2.col1,s2.col2, '00-1' dest FROM source1 s1 INNER JOIN source2 s2 ON s1.altunit = s2.unit INNER JOIN source3 s3 ON s1.unit = s3.unit WHERE sysd
SELECT s3.unit ,s2.col1,s2.col2, '00-1' dest
FROM source1 s1
INNER JOIN source2 s2 ON s1.altunit = s2.unit
INNER JOIN source3 s3 ON s1.unit = s3.unit
WHERE sysdate BETWEEN s1.e_date AND s1.d_date
AND s1.unit IN (SELECT unit FROM source1 WHERE u_sw = 1)
UNION
SELECT s3.price,s2.col1,s2.col2, '00-1' dest
FROM source1 s1
INNER JOIN source2 s2 ON s1.altunit = s2.unit
INNER JOIN source3 s3 ON s1.unit = s3.unit
WHERE sysdate BETWEEN s1.e_date AND s1.d_date
AND s1.unit IN (SELECT unit FROM source1 WHERE u_sw = 1)
UNION
SELECT s3.price,s2.col1,s2.col2, s2.dest
FROM source1 s1
INNER JOIN source2 s2 ON s1.altunit = s2.unit
INNER JOIN source3 s3 ON s1.unit = s3.unit
WHERE sysdate BETWEEN s1.e_date AND s1.d_date
AND s1.unit IN (SELECT unit FROM source1 WHERE u_sw = 1)
UNION
SELECT s3.cost,s2.col1,s2.col2, s2.dest
FROM source1 s1
INNER JOIN source2 s2 ON s1.altunit = s2.unit
INNER JOIN source3 s3 ON s1.unit = s3.unit
WHERE sysdate BETWEEN s1.e_date AND s1.d_date
AND s1.unit IN (SELECT unit FROM source1 WHERE u_sw = 1)
只有SELECT语句第一个位置的数据不同。剩余条件-JOIN和WHERE子句保持不变。我们只需要为选择的每1行发射4行:
SELECT variants.*
FROM source1 s1
INNER JOIN source2 s2 ON s1.altunit = s2.unit
INNER JOIN source3 s3 ON s1.unit = s3.unit
CROSS APPLY (
SELECT s3.unit ,s2.col1,s2.col2, '00-1' dest UNION
SELECT s3.price,s2.col1,s2.col2, '00-1' dest UNION
SELECT s3.price,s2.col1,s2.col2, s2.dest UNION
SELECT s3.cost,s2.col1,s2.col2, s2.dest
) variants
WHERE sysdate BETWEEN s1.e_date AND s1.d_date
AND s1.unit IN (SELECT unit FROM source1 WHERE u_sw = 1)
谷歌告诉我Oracle 10支持CTE,如果是真的,你可以这样做:
with tmp (unit, price, cost, col1, col2, dest1, dest2) as (
SELECT s3.unit, s3.price, s3.cost, s2.col1, s2.col2, s2.dest, '00-1'
FROM source1 s1
JOIN source2 s2
ON s1.altunit = s2.unit
JOIN source3 s3
ON s1.unit = s3.unit
WHERE sysdate BETWEEN s1.e_date AND s1.d_date
AND s1.unit IN (SELECT unit FROM source1 WHERE u_sw = 1)
)
select unit, col1, col2, dest2 from tmp
union
select price, col1, col2, dest2 from tmp
union
select price, col1, col2, dest1 from tmp
union
select cost, col1, col2, dest1 from tmp
我假设Oracle将以比原始查询更有效的方式对其进行评估。如果我读对了,除了select之外,所有四个子查询都是相同的。通常,最快的方法是通过使用交叉连接和条件逻辑来取消数据绑定:
SELECT (case when n.n = 1 then s3.unit
when n.n in (2, 3) then s3.price
when n.n = 4 then s3.cost
end) as unit,
s2.col1, s2.col2,
(case when n.n in (1, 2) then '00-1'
when n.n in (3, 4) then s2.dest
end) as dest
FROM source1 s1 INNER JOIN
source2 s2
ON s1.altunit = s2.unit INNER JOIN
source3 s3
ON s1.unit = s3.unit CROSS JOIN
(select 1 as n from dual union all select 2 from dual union all select 3 from dual union all select 4 from dual
) n
WHERE sysdate BETWEEN s1.e_date AND s1.d_date
AND s1.unit IN (SELECT unit FROM source1 WHERE u_sw = 1);
如果仍然需要消除重复项,请使用select distinct。交叉应用是一种方法,正如@usr建议的那样。
我只想在source1的SELECT unit中添加s1.unit,其中u_sw=1可能是性能杀手。
这取决于您可以拥有多少不同的单元:
如果从source1中选择unit,其中u_sw=1返回4个值,则保持如下状态。
如果返回的值超过40个,只需使用内部联接即可:
原件:
FROM source1 s1
[...]
WHERE
s1.unit IN (SELECT unit FROM source1 WHERE u_sw = 1)
致:
您正在重复source1中的SELECT unit,其中每个查询的u_sw=1。在运行要合并的查询之前,您应该预取此数据。甚至有什么区别?我看不出来。只有SELECT语句第一个位置的数据不同。剩余条件-JOIN和WHERE子句保持相同您使用的是什么DBMS?如果它支持CTE,它应该很容易优化,横向或交叉应用也会很容易改进things@Lennart我使用Oracle 10.2.0 64位,我想使用UNION,因为不应该有任何重复的行。很容易适应。如果不是,甲骨文肯定有一个相当的。
FROM source1 s1
INNER JOIN source1 s1limit
ON s1limit.unit = s1.unit
AND s1limit.u_sw = 1