消除数据库表中的重复

时间:2015-10-07 18:54:40

标签: sql db2

对于那些阅读原始问题的人,我很抱歉它太混乱了。我正在重做这个问题,使其更清晰(尽我所能)

我在DB2中有一个表,它使用不受我控制的条件从源数据库和数据填充。我的目标是创建一个预期的查询,以确保进入此目标表的数据符合预期。前5列将具有主键约束。

源数据有时可能在要作为主键的列中具有重复项。所以我需要让我的查询帐户。以下是记录可能的样子的一些示例。 (由于真实数据的隐私限制,我必须使用通用数据来说明)

Apple Banana Carrot Dog Elephant A+
Apple Banana Carrot Dog Elephant B
Apple Bowl Carrot Dog Elephant 231
Apple Bowl Carrot Dog Elephant A-
AppleJack Bowl Carrot Dog Elephant 142
AppleJack Bowl Carrot Dog Elephant 204

因此,如果我们将前5个记录视为主键的标准,那么我们在此处将有3个重复记录。前两个记录将是彼此的副本,接下来的两个记录和最后两个记录。以下是我选择保留哪些记录的标准。

1。)如果出现重复,请删除第6列值='NR'的记录 (在我的问题中没有这个例子,但它确实发生在我的实际数据中。

2.。)删除NR后,如果仍然出现重复项,请删除第6列值=数字的记录。如果两个记录都是数字,请保持

3.。)检查数字后,如果仍然出现重复项,请按字母顺序对第6列进行排序并记录第一个记录。

我需要我的查询在同时删除时检查这些条件。所以在我的查询执行后,唯一应该仍然存在的记录(根据我的理解如下):

Apple Banana Carrot Dog Elephant A+
Apple Bowl Carrot Dog Elephant A-
AppleJack Bowl Carrot Dog Elephant 142
AppleJack Bowl Carrot Dog Elephant 204

我希望这更清楚我需要什么。任何帮助将不胜感激!我永远感谢那些提供输入的人!这真的意味着很多!我仍然是SQL的新手,但了解大多数基本概念。再次感谢您花时间阅读。

2 个答案:

答案 0 :(得分:0)

示例(仅限数字的过滤器相当笨拙):

DELETE
-- SELECT * -- for testing
FROM rubbish d
WHERE EXISTS (
    SELECT *
    FROM rubbish x
    WHERE x.a=d.a
    AND x.b=d.b
    AND x.c=d.c
    AND x.d=d.d
    AND x.e=d.e
    AND (   0=1
            -- delete NR record only if a non-NR record exists
        OR  (d.val = 'NR' AND x.val <> 'NR')
            -- d=numeric, x= non numeric
        OR  (length(translate(d.val, '0123456789' , '' )) = 0
            AND length(translate(x.val, '0123456789' , '')) > 0
            )
            -- both numeric
       --  OR  (length(translate(d.val, '0123456789' , '' )) = 0
       --     AND length(translate(x.val, '0123456789' , '' )) = 0
       --     AND d.val::integer < x.val::integer
       --     )
            -- both non-numeric
        OR  (length(translate(d.val, '0123456789' , '' )) > 0
            AND length(translate(x.val, '0123456789' , '' )) > 0
            AND d.val > x.val AND x.val <> 'NR'
            )
        )
    )
    ;

答案 1 :(得分:0)

基本上你需要的是根据你的标准由前五列确定的组内的订单记录:首先是非数字,然后是数字,然后是“NR”,然后按字母顺序排序,并删除除每个第一条记录以外的所有记录组。所以举一个简单的例子:

create table t (f1 varchar(10), f2 varchar(10), f3 varchar(10))

insert into t values ('foo', 'bar', 'A+'), ('foo', 'bar', 'B'),
                     ('jack','jill','231'), ('jack','jill','A-'), 
                     ('apple', 'banana', '142'), ('apple', 'banana', '204'),
                     ('yum','sum','NR'), ('yum','sum','42')

首先尝试选择:

select * from (
  select 
  f1, f2, f3, 
  row_number() 
  over (partition by f1, f2
  order by 
    case 
        when f3 = 'NR' then 3 -- check for 'NR' first otherwise it will match the non-numeric check
        when length(trim(translate(f3,'','0123456789') )) > 0 then 1 -- non-numeric
        when length(trim(translate(f3,'','0123456789') )) = 0 then 2 -- numeric
        else 4 -- shouldn't happen anyway
    end,
    f3
    ) rn
    from t
) where rn = 1
order by f1, f2, f3

并删除:

delete from (  
  select 
  row_number() -- don't need any other columns
  over (partition by f1, f2
  order by 
    case 
        when f3 = 'NR' then 3
        when length(trim(translate(f3,'','0123456789')  )) > 0 then 1
        when length(trim(translate(f3,'','0123456789') )) = 0 then 2
        else 4
    end,
    f3
    ) rn
    from t
) where rn > 1

显然,在你的情况下,你会partition by五列,而不是两列。