当我遇到一个解决方案时,我正在阅读 A.Molinaro 的 SQL Cookbook。
它基于表
emp(empno,ename,job,mgr,hiredate,sal,comm,deptno)
和一个视图
V
它具有相同的列但不同的行。 mgr 和 comm 列可能为 NULL,其他列则不是。
书中的解决方案很长,并没有显示所有差异,尽管这是 3.7 中陈述的问题。
我制定了我的解决方案,它更短并显示了所有差异(意味着两个表中具有不同计数的所有行)。
select * from
# those which are contained in the (distinct) union of (col1,col2,...,coln, count) of both tables:
( select empno,ename,job,mgr,hiredate,comm,deptno, count(*) cnt from emp group by empno,ename,job,mgr,hiredate,comm,deptno
union
select empno,ename,job,mgr,hiredate,comm,deptno, count(*) cnt from V group by empno,ename,job,mgr,hiredate,comm,deptno
) as unionOfBoth
where (empno,ename,job,mgr,hiredate,comm,deptno,cnt)
not in
# those which are contained in the intersection of both tables with the equal number of counts:
( select e.empno,e.ename,e.job,e.mgr,e.hiredate,e.comm,e.deptno,e.cnt
from
(select empno, ename,job,mgr,hiredate,comm,deptno, count(*) cnt from emp group by empno,ename,job,mgr,hiredate,comm,deptno) e,
(select empno, ename,job,mgr,hiredate,comm,deptno, count(*) cnt from V group by empno,ename,job,mgr,hiredate,comm,deptno) v
where
e.empno = v.empno
and e.ename = v.ename
and e.job = v.job
and ifnull(e.mgr,0) = ifnull(v.mgr,0)
and e.hiredate = v.mgr
and e.deptno = v.deptno
and ifnull(e.comm,0) = ifnull(v.comm,0)
and e.cnt = v.cnt
);
基本上,您计算两个表中的不同行并进行联合(不是全部联合)以获得 tmp.table unionBoth。然后删除两个表共有的那些行。
这里表 t1 中的两行 r1 和表 t2 中的 r2 被认为是相同的,如果
(r1,count of r1 in t1) = (r2, count of r2 in t2),相当于r1=r2(在所有列上)和 (t1 中 r1 的计数)=(t2 中 r2 的计数).