我正在使用Oracle 11g。
我有2个相关的表:存储值(A)和要插入的新值(B)。它们之间都是相关的,ID为3列(客户端,组和人员代码)。每个表都有大约20个其他列(让我们称之为属性)。
我必须匹配它们以便我知道哪些值是新的(B中的id而不是A中的ID)所以我将它们插入A中,它们是等于(B中的id和具有相同属性的A中),它们是不是新值(A中的ID而不是B中的ID),所以我从存储的值(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
在此示例中,person 4是new,person 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个持续时间中的每一个都选择在不到10秒的时间内运行,但是当我使用UNION
或UNION ALL
合并它们时,完整查询会持续大约90秒,即使删除或者新的或者相等是空的。它可能在A或B中超过3000行。
有没有办法以更好,更快的方式获得这个结果?
答案 0 :(得分: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 :(得分:2)
如果表B包含您想要的数据,为什么不使用该表而不是表A中的表?创建一个同义词,指向包含正确数据的同义词并引用该词。
答案 2 :(得分:0)
好的,谢谢大家的回复。 我终于根据this blog中描述的策略,通过一些参数来传递一些参数来过滤前两个查询 整个过程现在持续30秒,如果A或B没有行,则为0(之前,它总是持续90秒)。 这个解决方案对我当前的程序影响较小。