如何删除表中ProductId为null且Name重复的多行数据?
解决方法:删除符合条件的行
要实现你想要的效果,我们需要精准定位到ProductId为null且对应Name在表中出现次数超过1次的行,然后删除它们。这里提供两种常用的SQL写法,适配不同的数据库环境:
方法1:使用关联子查询(兼容大部分数据库)
这种写法通过先统计每个Name的出现次数,再关联原表筛选目标行,适合所有支持基本SQL语法的数据库(比如MySQL 5.x、SQL Server、PostgreSQL等):
DELETE t1 FROM your_table t1 INNER JOIN ( -- 先找出所有出现次数超过1次的Name SELECT Name FROM your_table GROUP BY Name HAVING COUNT(*) > 1 ) t2 ON t1.Name = t2.Name -- 筛选出ProductId为null的行 WHERE t1.ProductId IS NULL;
逻辑说明
- 子查询
(SELECT Name FROM your_table GROUP BY Name HAVING COUNT(*) > 1)会得到Apple和Lemon这两个Name(因为它们在表中分别出现了3次和2次)。 - 将原表
t1和这个子查询结果关联,再加上ProductId IS NULL的条件,就能精准定位到要删除的行(Id=2和Id=8)。
方法2:使用窗口函数(适合支持窗口函数的数据库)
如果你的数据库支持窗口函数(比如MySQL 8.0+、PostgreSQL 9.4+、SQL Server 2012+等),可以用更直观的窗口函数写法:
DELETE FROM your_table WHERE Id IN ( SELECT Id FROM ( -- 给每一行加上对应Name的总出现次数 SELECT Id, ProductId, COUNT(*) OVER (PARTITION BY Name) AS name_total_count FROM your_table ) AS sub_query -- 筛选出符合条件的行ID WHERE name_total_count > 1 AND ProductId IS NULL );
逻辑说明
- 内层的窗口函数
COUNT(*) OVER (PARTITION BY Name)会计算每个Name在表中的总出现次数,比如Apple对应的行都会得到3,Lemon对应的行都会得到2。 - 外层筛选出总次数>1且ProductId为null的行ID,最后通过
Id IN (...)删除这些行。
注意:有些数据库(比如MySQL)不允许在DELETE语句中直接引用同一个表的窗口函数结果,所以需要套一层派生表
sub_query来规避这个限制。
这两种写法都能实现你想要的效果,执行后会保留Pear的null行(因为它只出现1次),删除Apple和Lemon的null行。
内容的提问来源于stack exchange,提问作者Business Man
相关产品推荐
相关产品推荐

