【问题标题】:Eliminate duplicate rows inside GROUP_CONCAT消除 GROUP_CONCAT 中的重复行
【发布时间】:2025-11-24 05:50:01
【问题描述】:

我有使用这个 sql 的重复记录:

SELECT emp.id, first_name, second_name, last_name, department, positions,  
            GROUP_CONCAT(email, " ", email_type SEPARATOR " || ") AS mails,
            GROUP_CONCAT(number, " ", number_type SEPARATOR " || ") AS numbers
            FROM geography.employee AS emp
            INNER JOIN geography.employee_email AS ee ON emp.id = ee.email_FK
            LEFT JOIN geography.employee_number AS en ON emp.id = en.number_FK
            WHERE first_name = 'John' AND last_name = 'Ausini'
            GROUP BY emp.id

所以我得到了这些邮件结果:

heyhey@abv.bg personal || heyhey@abv.bg personal || summer_geals@bwtc.co work || summer_geals@bwtc.co work || ivanov@abv.bg personal || ivanov@abv.bg personal 

对于数字:

+7654656656565 work || +7654656465655 personal || +7654656656565 work || +7654656465655 personal || +7654656656565 work || +7654656465655 personal

奇怪的是,在我的第二条记录中,邮件没有重复,邮件:

hei@abv.bg personal || hurei@abv.bg personal || burei@abv.bg personal || work@bwtc.com work

...但是在这条记录中我没有数字,也许这与顶部的数字有所不同。 我的预期输出不是这样重复每条记录的数据(对于第一条记录示例):

heyhey@abv.bg personal || summer_geals@bwtc.co work || ivanov@abv.bg personal

...而且数字也没有重复。 DISTINCT 也不起作用(如果我把它放在 SELECT 之后),我试过了,虽然我不喜欢掩盖问题。

我在表格中的数据:

【问题讨论】:

  • 当你加入多个一对多关系时,数字结果将乘以单独的多重匹配。如果您要查看类似的非分组查询的结果,您会看到每个电话号码与每个电子邮件配对。
  • 这个 group by 帮助我进行 group_concat,因为我需要获取两个同名记录的数据。如果我删除该组,我会在一列中收到 John Ausini 的两条记录的邮件。 @RaymondNijland
  • 另外请记住 GROUP_CONCAT 剪切字符串我相信默认值大约是 1000 字节,您需要手动设置更高的值,它在 MySQL 手册中..

标签: mysql sql group-by group-concat


【解决方案1】:

由于您只获取单个用户的信息,因此我会选择 Salman A 的答案;但是,如果您要为多个(或所有)用户服务,并且用户往往有很多电子邮件和号码,那么这个版本可能会更快。

SELECT emp.id, first_name, second_name, last_name, department, positions, ee.mails, en.numbers
FROM geography.employee AS emp
INNER JOIN (SELECT email_FK, GROUP_CONCAT(email, " ", email_type SEPARATOR " || ") AS mails 
            FROM geography.employee_email 
            GROUP BY email_FK
) AS ee ON emp.id = ee.email_FK
LEFT JOIN (SELECT number_FK, GROUP_CONCAT(number, " ", number_type SEPARATOR " || ") AS numbers 
           FROM geography.employee_number 
           GROUP BY number_FK
) AS en ON emp.id = en.number_FK
;

【讨论】:

  • @Ivanp 还请记住 GROUP_CONCAT 剪切字符串我相信默认值约为 1000 字节,您需要手动设置更高的值,它在 MySQL 手册中。在运行此查询之前使用SET SESSION group_concat_max_len = @@max_allowed_packet;
  • 绝对值得一提,尤其是因为它可以配置得更低;但我认为对于这种特殊情况,1000 对除了最多产的电子邮件帐户持有者之外的所有人来说已经绰绰有余了。 虽然我确实说过“很多电子邮件和号码”。
【解决方案2】:

MySQL GROUP_CONCAT 允许您指定DISTINCT,它应该在连接之前消除重复:

SELECT
    emp.id, first_name, second_name, last_name, department, positions,
    GROUP_CONCAT(DISTINCT email, " ", email_type SEPARATOR " || ") AS mails,
    GROUP_CONCAT(DISTINCT number, " ", number_type SEPARATOR " || ") AS numbers
FROM geography.employee AS emp
INNER JOIN geography.employee_email AS ee ON emp.id = ee.email_FK
LEFT JOIN geography.employee_number AS en ON emp.id = en.number_FK
WHERE first_name = 'John' AND last_name = 'Ausini'
GROUP BY emp.id

【讨论】:

  • SELECT emp.id, first_name, second_name, last_name, department, positions ... GROUP BY emp.id 看起来很可疑.. 因为它不是使用 SQL 的GROUP BY..的有效方法..
  • 特定配置下对MySQL有效。
  • 是的,如果 MySQL 服务器不运行 sql_mode ONLY FULL GROUP BY,它就会运行。但是 first_name、second_name、last_name、department、positions 列的值与组 emp.id 不匹配
  • ONLY_FULL_GROUP_BY;较新的 MySQL 版本的默认配置需要它。在这种特殊情况下,只需使用GROUP BY emp.id, first_name, second_name, last_name, department, positions 即可为此类配置修复它是微不足道的。 几乎任何不是滥用此功能的查询都可以轻松转换,
  • @RaymondNijland 这个特殊的例子可以正常工作。 emp.id 是主键。