PostgreSQL:
以下是示例表/数据
CREATE TABLE ident (
a INT
,b INT
,c INT
);
INSERT INTO ident
SELECT generate_series(10, 14)
,generate_series(100, 104)
,generate_series(210, 214);
INSERT INTO ident
SELECT unnest(array [1,1,1,1,1])
,unnest(array [1,1,1,1,1])
,unnest(array [1,1,1,1,1]);
由于表格没有primary/unique,我们可以使用ctid。
ctid
行版本在其表中的物理位置。注意
虽然 ctid 可用于非常快速地定位行版本,
如果一行被 VACUUM FULL 更新或移动,它的 ctid 将会改变。
因此 ctid 作为长期行标识符是无用的。 OID,或
更好的是用户定义的序列号,应该用于识别
逻辑行。
select ctid,* from ident;
将为您提供以下行
ctid a b c
------ -- --- ---
(0,1) 10 100 210
(0,2) 11 101 211
(0,3) 12 102 212
(0,4) 13 103 213
(0,5) 14 104 214
(0,6) 1 1 1
(0,7) 1 1 1
(0,8) 1 1 1
(0,9) 1 1 1
(0,10) 1 1 1
我们应该使用windows函数找到相同行的ctid
SELECT ctid
FROM (
SELECT ctid
,row_number() OVER (
PARTITION BY a
,b
,c ORDER BY ctid
) rn
FROM ident
) t
WHERE rn > 1
并从表中删除行
DELETE
FROM ident
WHERE ctid IN (
SELECT ctid
FROM (
SELECT ctid
,row_number() OVER (
PARTITION BY a
,b
,c ORDER BY ctid
) rn
FROM ident
) t
WHERE rn > 1
);
sqlfiddle
或
你可以简单地使用
delete from ident where ctid not in (
select min(ctid) from ident group by a,b,c
)