我有一个3列的表格,如下所示:
one | two | three | name
------------------------------------
A1 B1 C1 xyz
A1 B1 C1 pqr -> should be deleted
A1 B1 C1 lmn -> should be deleted
A2 B2 C2 abc
A2 B2 C2 def -> should be deleted
A3 B3 C3 ghi
------------------------------------
该表没有任何主键列。我对表没有任何控制,因此无法添加任何主键列。
如图所示,我要删除一列,两列和三列的组合相同的行。因此,如果A1B1C1发生了三次(例如上述情况),则应删除另外两个,而仅保留一个。
如何仅通过DB2中的一个查询来实现这一目标?
我的要求是进行单个查询,因为我将通过Java程序运行它。
最佳答案
(这假设您使用的是DB2 Linux/Unix/Windows版,其他平台可能会略有不同)
DELETE FROM
(SELECT ROWNUMBER() OVER (PARTITION BY ONE, TWO, THREE) AS RN
FROM SESSION.TEST) AS A
WHERE RN > 1;
应该可以为您提供所需的东西。
该查询使用OLAP function
ROWNUMBER()
为每个ONE
,TWO
和THREE
组合中的每一行分配一个数字。然后,DB2能够将fullselect
(A)引用的行与 DELETE
statement应该从表中删除的行进行匹配。为了能够将fullselect
用作delete子句的目标,它必须与deletable view的规则匹配(请参阅“注释”部分下的“可删除 View ”)。下面是一些证明(在LUW 9.7上测试):
DECLARE GLOBAL TEMPORARY TABLE SESSION.TEST (
one CHAR(2),
two CHAR(2),
three CHAR(2),
name CHAR(3)
) ON COMMIT PRESERVE ROWS;
INSERT INTO SESSION.TEST VALUES
('A1', 'B1', 'C1', 'xyz'),
('A1', 'B1', 'C1', 'pqr'),
('A1', 'B1', 'C1', 'lmn'),
('A2', 'B2', 'C2', 'abc'),
('A2', 'B2', 'C2', 'def'),
('A3', 'B3', 'C3', 'ghi');
DELETE FROM
(SELECT ROWNUMBER() OVER (PARTITION BY ONE, TWO, THREE) AS RN
FROM SESSION.TEST) AS A
WHERE RN > 1;
SELECT * FROM SESSION.TEST;
编辑2017年3月2日:
为了回答艾哈迈德·安瓦尔(Ahmed Anwar)的问题,如果您需要捕获已删除的内容,也可以将删除与“data change statement”组合使用。在此示例中,您可以执行类似以下的操作,这将为您提供“rn”列:一,二和三:
SELECT * FROM OLD TABLE (
DELETE FROM
(SELECT
ROWNUMBER() OVER (PARTITION BY ONE, TWO, THREE) AS RN
,ONE
,TWO
,THREE
FROM SESSION.TEST) AS A
WHERE RN > 1
) OLD;
关于sql - 在单个查询中从DB2中的表中删除重复的行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10087527/