在SQL中查找多个列的不匹配值

时间:2019-06-06 13:49:08

标签: sql

我有两个桌子

表1

col1    col2    col3    col4
v1      v2      v3      x
v4      v5      v6      y
v4      v5      v6      z
v7      v8      v9      w
v13     v14     v15     u

表2

col1    col2    col3    col5
v1      v2      v3      a
v1      v2      v3      b
v4      v5      v6      c
v10     v11     v12     d
v13     v14     v15     e

我想检查col1col2col3的那些表中的值是否完全相同。还有其他我不想考虑的列,例如col4。两个表中都没有主键。并且在col1col2col3中还会重复一些值。例如,在表1中,(v1,v2,v3)对(col1,col2,col3)重复两次。因此,这些也应在表2中重复相同的次数。

  • 以上(仅v13,v14,v15)匹配。
  • (v1,v2,v3)在表2中出现两次,但在表1中出现一次。
  • (v4,v5,v6)在表1中出现两次,但在表2中出现一次。
  • (v7,v8,v9)仅出现在表1中,而不出现在表2中。
  • (v10,v11,v12)仅出现在表2中,而不出现在表1中。

如何在单个查询中完成此操作?

3 个答案:

答案 0 :(得分:0)

您可以使用full join获取例外:

select coalesce(t1.col1, t2.col1) as col1,
       coalesce(t1.col2, t2.col2) as col2,
       coalesce(t1.col3, t2.col3) as col3,
       t1.cnt, t2.cnt
from (select col1, col2, col3, count(*) as cnt
      from table1
      group by col1, col2, col3
     ) t1 inner join  
     (select col1, col2, col3, count(*) as cnt
      from table2
      group by col1, col2, col3
    ) t2
    on t2.col1 = t1.col1 and t2.col2 = t1.col2 and t2.col3 = t1.col3 
where (t2.cnt <> t1.cnt) or (t1.cnt is null) or (t2.cnt is null);

如果只希望与cnt上的那些匹配,则可以使用内部联接。

答案 1 :(得分:0)

您可以创建两个子查询,这些子查询按1、2、3列分组并带有一个计数,然后将它们连接到列值和计数上

        select * 
  from (select col1, col2, col3, count(*) c
          from table1
         group by col1, col2, col3) t1
  join (select col1, col2, col3, count(*) c
          from table2
         group by col1, col2, col3) t2 
    on t2.col1 = t1.col1
   and t2.col2 = t2.col2
   and t2.col3 = t3.col3
   and t2.c = t1.c

答案 2 :(得分:0)

您可以通过此查询找到所有匹配的元组:

select col1, col2, col3
  from (select col1, col2, col3, count(*) cnt 
          from table1
         group by col1, col2, col3) t1
  join (select col1, col2, col3, count(*) cnt
          from table2
         group by col1, col2, col3) t2
 using (col1, col2, col3, cnt)

Results

| col1 | col2 | col3 |
|------|------|------|
|  v13 |  v14 |  v15 |

然后,您可以采用上述查询的结果来分别确定原始表中不匹配的记录:

select *
  from table1
 where (col1,col2,col3) not in (  
    select col1, col2, col3
      from (select col1, col2, col3, count(*) cnt 
              from table1
             group by col1, col2, col3) t1
      join (select col1, col2, col3, count(*) cnt
              from table2
             group by col1, col2, col3) t2
      using (col1, col2, col3, cnt));

Results

| col1 | col2 | col3 | col4 |
|------|------|------|------|
|   v1 |   v2 |   v3 |    x |
|   v4 |   v5 |   v6 |    y |
|   v4 |   v5 |   v6 |    z |
|   v7 |   v8 |   v9 |    w |

select *
  from table2
 where (col1,col2,col3) not in (  
    select col1, col2, col3
      from (select col1, col2, col3, count(*) cnt 
              from table1
             group by col1, col2, col3) t1
      join (select col1, col2, col3, count(*) cnt
              from table2
             group by col1, col2, col3) t2
      using (col1, col2, col3, cnt));

Results

| col1 | col2 | col3 | col5 |
|------|------|------|------|
|   v1 |   v2 |   v3 |    a |
|   v1 |   v2 |   v3 |    b |
|   v4 |   v5 |   v6 |    c |
|  v10 |  v11 |  v12 |    d |

或全部在一起:

select * from (
    select 't1' src, t1.*
      from table1 t1
    union all
    select 't2' src, t1.*
      from table1 t1) u1
 where (col1,col2,col3) not in (  
    select col1, col2, col3
      from (select col1, col2, col3, count(*) cnt 
              from table1
             group by col1, col2, col3) t1
      join (select col1, col2, col3, count(*) cnt
              from table2
             group by col1, col2, col3) t2
      using (col1, col2, col3, cnt));

Results

| src | col1 | col2 | col3 | col4 |
|-----|------|------|------|------|
|  t1 |   v1 |   v2 |   v3 |    x |
|  t1 |   v4 |   v5 |   v6 |    y |
|  t1 |   v4 |   v5 |   v6 |    z |
|  t1 |   v7 |   v8 |   v9 |    w |
|  t2 |   v1 |   v2 |   v3 |    x |
|  t2 |   v4 |   v5 |   v6 |    y |
|  t2 |   v4 |   v5 |   v6 |    z |
|  t2 |   v7 |   v8 |   v9 |    w |

通过SQL Fiddle

观看所有操作