我有 2 个表,我需要做一个表比较:
TABLE A
LABEL
VALUE
TABLE B
LABEL
VALUE
基本上我想要:
- 匹配标签上的值不相等的记录 表
- A 中不在表 B 中的记录 表
- B 中不在表 A 中的记录
有了这些信息,我就可以记录我需要的适当历史数据。 它将向我显示值已更改的位置,或者添加或删除标签的位置......您可以说表 A 是"新"数据集,表 B 是"旧"数据集。 因此,我可以看到正在添加的内容,已删除的内容以及更改的内容。
一直在尝试使用UNION和MINUS,但还没有运气。
像这样:
A LABEL A VALUE B LABEL B VALUE
---------------------------------------
XXX 5 XXX 3
YYY 2
ZZZ 4
WWW 7 WWW 8
如果标签和值相同,则结果集中不需要它们。
这是解决此问题的一种方法(也可能是最有效的方法)。主要部分是对结果执行UNION ALL
和GROUP BY
的子查询,仅保留由单行组成的组。(具有两行的组是两个表中存在相同行的组。这种方法是由Marco Stefanetti发明的,首先在AskTom讨论板上讨论过。与更常见的"对称差分"方法相比,这种方法的好处是每个基表只读取一次,而不是两次。
然后,为了将结果放入所需的格式,我使用PIVOT
操作(从 Oracle 11.1 开始可用);在早期版本的 Oracle 中,也可以使用标准聚合外部查询完成相同的操作。
请注意,我修改了输入以显示VALUE
列中NULL
的处理。
重要提示:此解决方案假定LABEL
是两个表中的主键;如果不是,则不清楚所需的输出如何有意义。
with
table_a ( label, value ) as (
select 'AAA', 3 from dual
union all select 'CCC', null from dual
union all select 'XXX', 5 from dual
union all select 'WWW', 7 from dual
union all select 'YYY', 2 from dual
union all select 'HHH', null from dual
),
table_b ( label, value ) as (
select 'ZZZ', 4 from dual
union all select 'AAA', 3 from dual
union all select 'HHH', null from dual
union all select 'WWW', 8 from dual
union all select 'XXX', 3 from dual
union all select 'CCC', 1 from dual
)
-- End of test data (NOT PART OF THE SOLUTION!) SQL query begins below this line.
select a_label, a_value, b_label, b_value
from (
select max(source) as source, label as lbl, label, value
from (
select 'A' as source, label, value
from table_a
union all
select 'B' as source, label, value
from table_b
)
group by label, value
having count(*) = 1
)
pivot ( max(label) as label, max(value) as value for source in ('A' as a, 'B' as b) )
;
输出:
A_LABEL A_VALUE B_LABEL B_VALUE
------- ------- ------- -------
YYY 2
CCC CCC 1
WWW 7 WWW 8
ZZZ 4
XXX 5 XXX 3