moe*_*moe 41 sql database postgresql duplicates netezza
我的表中有重复的行,我想以最有效的方式删除重复项,因为表很大.经过一番研究,我得出了这个问题:
WITH TempEmp AS
(
SELECT name, ROW_NUMBER() OVER(PARTITION by name, address, zipcode ORDER BY name) AS duplicateRecCount
FROM mytable
)
-- Now Delete Duplicate Records
DELETE FROM TempEmp
WHERE duplicateRecCount > 1;
Run Code Online (Sandbox Code Playgroud)
但它只适用于SQL,而不适用于Netezza.它似乎不喜欢DELETE后面的WITH条款?
Gor*_*off 52
如果您没有其他唯一标识符,则可以使用ctid:
delete from mytable
where exists (select 1
from mytable t2
where t2.name = mytable.name and
t2.address = mytable.address and
t2.zip = mytable.zip and
t2.ctid > mytable.ctid
);
Run Code Online (Sandbox Code Playgroud)
在每个表中都有一个唯一的,自动递增的id是个好主意.这样做delete是一个重要原因.
isa*_*pir 36
我喜欢@ erwin-brandstetter的解决方案,但希望用USING关键字显示解决方案:
DELETE FROM table_with_dups T1
USING table_with_dups T2
WHERE T1.ctid < T2.ctid -- delete the "older" ones
AND T1.name = T2.name -- list columns that define duplicates
AND T1.address = T2.address
AND T1.zipcode = T2.zipcode;
Run Code Online (Sandbox Code Playgroud)
如果你想删除它们之前查看的记录,然后只需更换DELETE用SELECT *和USING用逗号,,即
SELECT * FROM table_with_dups T1
, table_with_dups T2
WHERE T1.ctid < T2.ctid -- select the "older" ones
AND T1.name = T2.name -- list columns that define duplicates
AND T1.address = T2.address
AND T1.zipcode = T2.zipcode;
Run Code Online (Sandbox Code Playgroud)
更新:我在这里测试了一些不同的解决方案以提高速度.如果你不期望有很多重复,那么这个解决方案比具有NOT IN (...)子句的那个更好,因为它们在子查询中生成了很多行.
如果您重写要使用的查询,IN (...)那么它的执行方式与此处提供的解决方案类似,但SQL代码变得简洁得多.
更新2:如果您NULL在其中一个键列中有值(您实际上不应该IMO),那么您可以COALESCE()在该列的条件中使用,例如
AND COALESCE(T1.col_with_nulls, '[NULL]') = COALESCE(T2.col_with_nulls, '[NULL]')
Run Code Online (Sandbox Code Playgroud)
Erw*_*ter 22
在一个完美的世界中,每个表都有某种唯一的标识符.
在不存在任何唯一的列(或其组合)的,使用的ctid柱:
DELETE FROM tbl
WHERE ctid NOT IN (
SELECT min(ctid) -- ctid is NOT NULL by definition
FROM tbl
GROUP BY name, address, zipcode); -- list columns defining duplicates
Run Code Online (Sandbox Code Playgroud)
上述查询很简单,只列出一次列名.NOT IN (SELECT ...)当涉及NULL值时,是一种棘手的查询样式,但系统列ctid永远不会为NULL.看到:
使用@GordonEXISTS所证明的通常更快.因此,像@isapir这样的USING子句后来添加了一个自连接.两者都应该导致相同的查询计划.
但请注意一个重要区别:这些其他查询将NULL值视为不相等,而GROUP BY(DISTINCT或DISTINCT ON ())将NULL值视为相等.如果定义了键列,则无关紧要NOT NULL.否则,根据您对"重复"的定义,您将需要一种或另一种方法.或者用于IS NOT DISTINCT FROM比较值(可能无法使用某些索引).
免责声明:
ctid是Postgres的内部实现细节,它不在SQL标准中,可以在没有警告的情况下在主要版本之间进行更改(即使这不太可能).由于后台进程或并发写操作(但不在同一命令中),其值可以在命令之间更改.
有关:
在旁边:
DELETE语句的目标不能是CTE,只能是基础表.这是SQL Server的溢出效应 - 就像你的整个方法一样.
Bru*_*lza 10
这是我想出来的,使用一个 group by
DELETE FROM mytable
WHERE id NOT in (
SELECT MIN(id)
FROM mytable
GROUP BY name, address, zipcode
)
Run Code Online (Sandbox Code Playgroud)
它删除重复项,保留最旧的重复记录.
我们可以使用窗口函数来非常有效地删除重复行:
DELETE FROM tab
WHERE id IN (SELECT id
FROM (SELECT row_number() OVER (PARTITION BY column_with_duplicate_values), id
FROM tab) x
WHERE x.row_number > 1);
Run Code Online (Sandbox Code Playgroud)
一些PostgreSQL的优化版本(带有ctid):
DELETE FROM tab
WHERE ctid = ANY(ARRAY(SELECT ctid
FROM (SELECT row_number() OVER (PARTITION BY column_with_duplicate_values), ctid
FROM tab) x
WHERE x.row_number > 1));
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
54754 次 |
| 最近记录: |