使用count(*) over(partition by...)
可以简单高效地定位不必要的重复项,同时列出所有受影响的行和所需的所有列:
SELECT
t.*
FROM (
SELECT
s.*
, COUNT(*) OVER (PARTITION BY s.name, s.city) AS qty
FROM stuff s
) t
WHERE t.qty > 1
ORDER BY t.name, t.city
尽管大多数最近的关系型数据库管理系统版本支持count(*) over(partition by...)
,但MySQL V 8.0引入了“窗口函数”,如下所示(在MySQL 8.0中)
CREATE TABLE stuff(
id INTEGER NOT NULL
,name VARCHAR(60) NOT NULL
,city VARCHAR(60) NOT NULL
);
INSERT INTO stuff(id,name,city) VALUES
(904834,'jim','London')
, (904835,'jim','London')
, (90145,'Fred','Paris')
, (90132,'Fred','Paris')
, (90133,'Fred','Paris')
, (923457,'Barney','New York') # not expected in result
;
SELECT
t.*
FROM (
SELECT
s.*
, COUNT(*) OVER (PARTITION BY s.name, s.city) AS qty
FROM stuff s
) t
WHERE t.qty > 1
ORDER BY t.name, t.city
id | name | city | qty
-----: | :--- | :----- | --:
90145 | Fred | Paris | 3
90132 | Fred | Paris | 3
90133 | Fred | Paris | 3
904834 | jim | London | 2
904835 | jim | London | 2
db<>fiddle 这里
窗口函数。 MySQL现在支持窗口函数,它们针对查询的每一行执行计算,使用与该行相关的行。这些函数包括RANK()、LAG()和NTILE()等函数。此外,现在可以将几个现有的聚合函数用作窗口函数;例如,SUM()和AVG()。有关更多信息,请参见第12.21节“窗口函数”。
null
,那么(除非我漏掉了什么)您需要将它更改为CROSS JOIN
(全笛卡尔积),然后添加一个WHERE
子句,例如:WHERE ((s.name = t.name) OR (s.name is null and t.name is null)) AND ((s.city = t.city) OR (s.city is null and t.city is null))
。 - Adam Parkin