对于那些阅读原始问题的人,我很抱歉它太混乱了。我正在重做这个问题,使其更清晰(尽我所能)
我在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的新手,但了解大多数基本概念。再次感谢您花时间阅读。
答案 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
五列,而不是两列。