PostgreSQL中如何删除name列存在重复值的冗余行及解决row_num列不存在报错
解决PostgreSQL删除重复行的报错问题
嘿,你遇到的问题其实是两个小细节导致的:一是混用了SQL Server的语法,二是没注意PostgreSQL对CTE删除的限制,我来一步步帮你解决:
报错的直接原因
你写的row_num = row_number()是SQL Server里定义列别名的写法,但PostgreSQL里必须用AS关键字来指定别名,所以这行应该改成:
row_number() over (partition by name order by ID) AS row_num
第二个问题:PostgreSQL不能直接删除CTE中的行
即使修正了别名,你原来的delete from cte写法在PostgreSQL里也不生效——PostgreSQL不支持直接从CTE执行删除操作,你需要通过CTE关联原表来定位要删除的行。
正确的SQL写法
这里提供两种可行的方案,都能实现你要的“每个name只保留唯一行(保留id最小的那一条)”的需求:
方案一:CTE + DELETE USING(清晰直观)
WITH cte AS ( SELECT id, row_number() OVER (PARTITION BY name ORDER BY id) AS row_num FROM public.tentacle_ticker ) DELETE FROM public.tentacle_ticker USING cte WHERE public.tentacle_ticker.id = cte.id AND cte.row_num > 1;
这个逻辑是:先给每个name分组里的行按id排序编号,然后通过USING关联原表,删除编号大于1的行(也就是保留每个分组里最小编号的行)。
方案二:WHERE EXISTS(更简洁)
如果不需要CTE,也可以用子查询直接实现:
DELETE FROM public.tentacle_ticker t1 WHERE EXISTS ( SELECT 1 FROM public.tentacle_ticker t2 WHERE t2.name = t1.name AND t2.id < t1.id );
这个写法的逻辑是:删除那些存在同name但id更小的行,最终每个name只会保留id最小的那一行,效果和方案一完全一致。
执行任意一种方案后,你的表就会得到期望的结果:
id | name | symbol
1 | Two | Three
3 | Three | Three
内容的提问来源于stack exchange,提问作者JSRB
相关产品推荐
相关产品推荐

