场景如下,前段时间同事不小心跑了一个类似的查询
DELETE FROM app_i18n WHERE disabled = 0 and translation is null or translation = '';
这是app_i18n的表结构
CREATE TABLE app_i18n (
`id` INTEGER(11) NOT NULL AUTO_INCREMENT,
`category` INTEGER(11) unsigned NOT NULL,
`keyword` varchar(50) DEFAULT NULL,
`language` varchar(2) NOT NULL DEFAULT 'en',
`translation` text NOT NULL,
`disabled` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY (`category`, `keyword`, `language`, `disabled`)
) ENGINE=InnoDB;
由此产生的问题是,其中一些“翻译”虽然是空的,但存在是有原因的。所以恢复是为了。从数据库的旧副本中,他恢复了所有为空或空且未禁用的行。
未知数量的其他开发人员迅速投入“翻译”以解决他们遇到的问题,使问题变得更加复杂。所以我认为解决方案是
SELECT id
FROM app_i18n
WHERE disabled = 0
AND (translation is null or translation = '')
GROUP BY category, keyword, language
HAVING COUNT(id) > 1;
该查询会产生我想要的答案吗?即所有具有重复类别的记录,具有重复的相同语言的关键字?
在大多数 RDBMS 上,您的查询会导致错误。我相信 MySQL 会返回一个结果,但不一定是您要查找的结果。
当您按一组列分组时,只有在 group by 子句中提到的列也可以直接在 select 子句中提到。所有其他列都必须包含在某种聚合中,如 MAX() 或 AVG()。
您正在寻找具有重复条目的所有类别、关键字和语言组合。所以你希望你的查询返回这些列:
如果您想要具有非唯一类别、关键字和语言组合的行的所有列,您需要添加一个连接:
MySQL 有一个 GROUP_CONCAT 函数,因此您可以获得与重复记录匹配的逗号分隔的 id 列表。
或者
对于漂亮的 JSON id
参见http://sqlfiddle.com/#!2/3b51a/6进行演示