Che*_*ain 1 postgresql duplication subquery
我一直在学习Postgres(来自SQL Server),这个错误真的让我很困惑。
\n\n这是带有一些示例数据的代码:
\n\ncreate table T (\nID serial primary key,\nA varchar(1),\nB varchar(1),\nC varchar(1)\n)\n
Run Code Online (Sandbox Code Playgroud)\n\n\xe2\x86\x91 测试表。
\n\ninsert into T (A, B, C)\nvalues('A', 'B', 'C'), ('A', 'B', 'C')\n
Run Code Online (Sandbox Code Playgroud)\n\n\xe2\x86\x91 插入重复项
\n\ndelete from T\nwhere ID in (\n select t.ID\n from ( select ID, row_number() over (partition by A,B,C order by A,B,C) as rn\n from T) as t\n where t.rn < (select max(t.rn) from t)\n )\n
Run Code Online (Sandbox Code Playgroud)\n\n\xe2\x86\x91 删除重复项并保留最后一个条目。
\n\n问题在于(select max(t.rn) from t)
我假设这是一个菜鸟错误,与在引用带有别名的列时不知道 postgres 语法有关?
首先,partition by A,B,C order by A,B,C
没有任何意义。由于您打算保留“最后”行(即具有最大的行ID
),因此您可能的意思是:
partition by A,B,C order by ID
Run Code Online (Sandbox Code Playgroud)
尽管如此,语法还是无效的。此子查询表达式包含对外部查询的列的引用:(select max(t.rn) from t)
。子查询的范围不包括外部查询中的列,因此rn
在其中不可见。只有表的列t
是。
您可以使用 CTE 来允许引用并使语法有效:
WITH cte AS (SELECT id, row_number() OVER (PARTITION by a,b,c ORDER BY id) AS rn FROM t)
DELETE FROM t
WHERE id IN (
SELECT id
FROM cte
WHERE rn < (SELECT max(rn) FROM cte)
)
Run Code Online (Sandbox Code Playgroud)
尽管如此,这个问题仍然是危险的废话。不要使用这个!
与最大行数进行比较在逻辑上是无意义的,因为每组对等点可能有不同数量的重复项。会删除比应有的多得多的内容。
更简单、更正确:
DELETE FROM t
WHERE id IN (
SELECT t1.id
FROM (SELECT id, row_number() OVER (PARTITION by a,b,c ORDER BY id DESC) AS rn FROM t) t1
WHERE t1.rn > 1 -- all but the latest
);
Run Code Online (Sandbox Code Playgroud)
反过来,可以更便宜地获得(假设所有列NOT NULL
!):
DELETE FROM t
WHERE EXISTS (
SELECT FROM t AS t1
WHERE t1.a = t.a
AND t1.b = t.b
AND t1.c = t.c
AND t1.id > t.id
);
Run Code Online (Sandbox Code Playgroud)
“……存在具有更大 ID 的受骗者”。
有关的:
归档时间: |
|
查看次数: |
17052 次 |
最近记录: |