子查询中MySQL按函数依赖分组

子查询中MySQL按函数依赖分组,mysql,Mysql,我正在编写一个查询,以查找人员表中的重复行,包括每个重复行: SELECT * FROM Person WHERE CONCAT(firstName,lastName) IN ( SELECT CONCAT(firstName,lastName) AS name FROM Person GROUP BY CONCAT(firstName,lastName) HAVING COUNT(*) > 1 ) 在MySQL 8.0.19中仅启用_FULL _GROU

我正在编写一个查询,以查找人员表中的重复行,包括每个重复行:

SELECT *
FROM Person
WHERE CONCAT(firstName,lastName) IN (
    SELECT CONCAT(firstName,lastName) AS name
    FROM Person
    GROUP BY CONCAT(firstName,lastName)
    HAVING COUNT(*) > 1
)
在MySQL 8.0.19中仅启用_FULL _GROUP _BY时运行此程序,失败原因如下:

查询1错误:HAVING子句的表达式1不在GROUP BY子句中,并且包含未聚合的列“Person.firstName”,该列在功能上不依赖于GROUP BY子句中的列;这与sql\u mode=only\u full\u group\u by不兼容

我想不出怎么解决这个问题。我试着把COUNT*改成COUNTCONCATfirstName,lastName,但没用

奇怪的是,a在MariaDB 10.2中运行良好,无论是否只有_FULL_GROUP_BY,b单独运行子查询都不会引起任何问题

我做错了什么?这几乎像是MySQL中的一个bug


[编辑]:我当然很欣赏我的问题的其他解决方案,但是我对出现错误的原因的答案非常感兴趣。

尝试下面的方法,它将与您尝试的方法相同

SELECT *
FROM Person
WHERE (firstName,lastName) IN (
    SELECT firstName,lastName
    FROM Person
    GROUP BY firstName,lastName
    HAVING COUNT(*) > 1
)
不合并字段:

SELECT *
FROM Person
WHERE (firstName,lastName) IN (
    SELECT firstName,lastName AS name
    FROM Person
    GROUP BY firstName,lastName
    HAVING COUNT(*) > 1
)
或使用任何_值函数:

SELECT *
FROM Person
WHERE CONCAT(firstName,lastName) IN (
    SELECT ANY_VALUE(CONCAT(firstName,lastName)) AS name
    FROM Person
    GROUP BY CONCAT(firstName,lastName)
    HAVING COUNT(*) > 1
)

我将使用exists逻辑编写您的查询:

SELECT p1.*
FROM Person p1
WHERE EXISTS (SELECT 1 FROM Person p2
              WHERE p2.firstName = p1.firstName AND
                    p2.lastName = p1.lastName AND
                    p2.id <> p1.id);
这将允许快速评估现有查找。注意,在InnoDB上,MySQL应该通过将id添加到上述两列索引的末尾来自动覆盖id

关于您的错误,我不禁想知道,问题是否在于您在子查询中没有使用正确的别名,导致MySQL认为您引用的是外部查询中的列。请尝试以下版本:

SELECT p1.*
FROM Person p1
WHERE CONCAT(firstName, lastName) IN (
    SELECT CONCAT(p2.firstName, p2.lastName)
    FROM Person p2
    GROUP BY CONCAT(p2.firstName, p2.lastName)
    HAVING COUNT(*) > 1
);

firstName='Song',lastName='Ji Yang'和firstName='Song Ji',lastName='Yang'记录必须被检测为重复记录吗?@Akina,是的,这两个记录应该被检测为重复记录。如果是这样,请注意在连接过程中必须添加分隔符!因为直接连接将分别给出两个不同的值“宋继阳”和“宋继阳”。您必须规范化值中的分隔符-假设值中的单词之间有2或3个空格字符…@Akina,明白了,这在我的实际查询中得到了处理。查询1-您从哪里获取了某个id?查询2-将没有帮助。@Akina如果没有主键存在,那么OP应该首先修复它。一般来说,每个表都应该有一个主键。为什么你要在我的回答下开始一个冗长的讨论,当我建议使用EXISTS最有可能是解决OP问题的最有效方法时?我并不是说WHERE EXISTS比WHERE IN更有效-我只是说它可能不适用于这种特殊情况。我不知道为什么,但你的“EXISTS”建议在我的~12k数据集上执行需要45秒的时间排。感谢您对错误的建议,但是添加别名并不能解决此问题。请避免在其他人的回答下开始长时间的讨论。感谢您的建议,ANY_VALUE方法确实适合我!但是你知道是什么导致了我的错误吗?@Gannet这是MySQL的问题-它没有检测到GroupBy和output中使用的表达式是相同的,甚至字面上也是一样的。即使在GROUP BY中使用输出字段名:SELECT CONCATfirstName,lastName作为Person GROUP BY name中的名称,且COUNT*>1,也会导致相同的错误。因此,您认为这只是MySQL的一个限制,任何_值都是正确的解决方法吗?还是我应该报告的错误?@Gannet ANY_值是一个函数,其目的是消除组中非分组字段的多含义问题。或者我怀疑这是一只虫子。它依赖于SQL模式,如用户手册所述。所以这是一个特征。
SELECT p1.*
FROM Person p1
WHERE CONCAT(firstName, lastName) IN (
    SELECT CONCAT(p2.firstName, p2.lastName)
    FROM Person p2
    GROUP BY CONCAT(p2.firstName, p2.lastName)
    HAVING COUNT(*) > 1
);