如何测试表中的所有行是否都重复(一列除外)

时间:2019-06-29 18:12:27

标签: sql db2 compare db2-luw sql-null

我正在使用一个数据仓库表,该表可以分为声明的行和计算的行。 我怀疑所计算的行是所声明的行的完美副本(所声明/计算的列除外)。

我尝试使用except子句对此进行测试:

但是所有记录都已返回。我不认为这是可能的,而且我怀疑这是由于null值造成的。

有没有一种方法可以比较将空值与空值进行比较的记录?

SELECT a, b, c FROM table WHERE clm_cmp_cd = 'clm'
    EXCEPT
SELECT a, b, c FROM table WHERE clm_cmp_cd = 'cmp'

但是所有记录都已返回。我不认为这是可能的,而且我怀疑这是由于null值造成的。

有没有一种方法可以比较将空值与空值进行比较的记录?

edit:解决方案应使用任意数量的字段,且类型不同。在这种情况下,我有〜100个字段,其中有2/3的字段可能为空值。这是一个数据仓库,必须预期一定程度的非规范化。

edit:我在限制自己为非null列的同时测试了查询,并且得到了我期望的结果(无)。 但是,我仍然想比较可能包含空值的字段。

2 个答案:

答案 0 :(得分:0)

您的假设似乎是错误的。您可以尝试以下方法:

select a, b, c,
       sum(case when clm_cmp_cd = 'clm' then 1 else 0 end) as num_clm,
       sum(case when clm_cmp_cd = 'cmp' then 1 else 0 end) as num_cmp
from t
group by a, b, c;

这将向您显示三列的值以及每种类型的匹配数。

您的问题可能是看起来相似的值并不完全相同。这可能是由于浮点数略有差异,或者是由于字符串中不匹配的字符(例如前导空格)引起的。

答案 1 :(得分:0)

让我们看看Db2如何与NULLGROUP BY中的INTERSECT值一起工作:

with t(a, b, clm_cmp_cd) as (values
  (   1, 1, 'clm')
, (   1, 1, 'cmp')
, (null, 1, 'clm')
, (null, 1, 'cmp')
, (   2, 1, 'cmp')
)
select a, b
from t
where clm_cmp_cd='clm'
  intersect
select a, b
from t
where clm_cmp_cd='cmp';

with t(a, b, clm_cmp_cd) as (values
  (   1, 1, 'clm')
, (   1, 1, 'cmp')
, (null, 1, 'clm')
, (null, 1, 'cmp')
, (   2, 1, 'cmp')
)
select a, b
from t
where clm_cmp_cd in ('clm', 'cmp')
group by a, b
having count(1)>1;

两个查询都返回相同的结果:

     A  B
    -- --
     1  1
<null>  1
这些运算符将

NULL值视为相同。
如果表中的列太多,无法在查询中手动指定它们,则可以使用以下查询生成列列表:

select listagg(colname, ', ')
from syscat.columns
where tabschema='MYSCHEMA' and tabname='TABLE' and colname<>'CLM_CMP_CD';