MySQL GROUP_CONCAT 防止不必要的重复

Posted

技术标签:

【中文标题】MySQL GROUP_CONCAT 防止不必要的重复【英文标题】:MySQL GROUP_CONCAT prevent unnecessary duplicates 【发布时间】:2017-12-18 09:04:36 【问题描述】:

我正在从本地 WordPress (bbPress) 安装导出一些数据,并且在我的 GROUP_CONCAT 列(数据库中不存在)中遇到重复数据。

这是查询:

SELECT 
    a.`ID`, a.`post_date`, a.`post_content`, a.`post_title`, 
    a.`post_status`, a.`post_name`, a.`post_type`, a.`post_parent`, 
    GROUP_CONCAT(d.`meta_key` SEPARATOR '|') AS `post_meta_keys`, 
    GROUP_CONCAT(d.`meta_value` SEPARATOR '|') AS `post_meta_values`, 
    b.`user_login`, b.`user_pass`, b.`user_nicename`, b.`user_email`, 
    b.`user_registered`, b.`display_name`, 
    GROUP_CONCAT(c.`meta_key` SEPARATOR '|') AS `user_meta_keys`, 
    GROUP_CONCAT(c.`meta_value` SEPARATOR '|') AS `user_meta_values` 
FROM 
    `wp_posts` a 
INNER JOIN 
    `wp_users` b ON a.`post_author` = b.`ID` 
INNER JOIN 
    `wp_usermeta` c ON a.`post_author` = c.`user_id` 
INNER JOIN 
    `wp_postmeta` d ON a.`ID` = d.`post_id` 
WHERE 
    `post_type` = 'forum' OR 
    `post_type` = 'topic' OR 
    `post_type` = 'reply' 
GROUP BY 
    a.`ID`

我正在尝试获取一个大视图,其中包含帖子、其元信息以及每一行中的作者信息。一切都很好,除了 GROUP_CONCAT 列有多个重复项。例如:从结果集的第一行开始 - user_meta_keys 列具有以下值:

[0] => nickname
[1] => first_name
[2] => last_name
[3] => description
[4] => rich_editing
[5] => comment_shortcuts
[6] => admin_color
[7] => use_ssl
[8] => show_admin_bar_front
[9] => locale
[10] => wp_capabilities
[11] => wp_user_level
[12] => dismissed_wp_pointers
[13] => show_welcome_panel
[14] => session_tokens
[15] => wp_dashboard_quick_press_last_post_id
[16] => community-events-location
[17] => managenav-menuscolumnshidden
[18] => metaboxhidden_nav-menus
[19] => nav_menu_recently_edited
[20] => users_per_page
[21] => wp__bbp_topic_count
[22] => wp__bbp_reply_count
[23] => nickname
[24] => first_name
[25] => last_name
[26] => description
[27] => rich_editing
[28] => comment_shortcuts
[29] => admin_color
[30] => use_ssl
[31] => show_admin_bar_front
[32] => locale
[33] => wp_capabilities
[34] => wp_user_level
[35] => dismissed_wp_pointers
[36] => show_welcome_panel
[37] => session_tokens
[38] => wp_dashboard_quick_press_last_post_id
[39] => community-events-location
[40] => managenav-menuscolumnshidden
[41] => metaboxhidden_nav-menus
[42] => nav_menu_recently_edited
[43] => users_per_page
[44] => wp__bbp_topic_count
[45] => wp__bbp_reply_count
[46] => nickname
[47] => first_name
[48] => last_name
[49] => description
[50] => rich_editing
[51] => comment_shortcuts
[52] => admin_color
[53] => use_ssl
[54] => show_admin_bar_

昵称重复了 3 次,许多其他字段也是如此。我已经进行了一些搜索,看起来其他人也经历过这种情况。有些人通过在分组列上使用“DISTINCT”来解决它 - 但这对我不起作用,因为某些值实际上是重复的。

所以我的问题是:

1) 有人可以向我解释为什么 GROUP_CONCAT 列有这么多重复项以及查询是否写错 - 我至少会计算出“键”列和“值”列之间匹配的计数 - 但它们也不要。

2) 可以调整查询以完成我要查找的内容吗?

感谢您的宝贵时间!

-- 编辑#1-- 好吧,一个错误是我忘记在 mysql 中将 GROUP_CONCAT 限制设置得更高——所以现在我正在升级,我认为我越来越接近了。

-- 编辑#2-- 看起来 GROUPS 的重复行数与每个备用表中的行数一样多?含义... postmeta 表中有 8 行与 post id 匹配,因此 usermeta 结果中有 8 个重复的组...或者 usermeta 表中有 23 行与用户 id 匹配,因此有 23 个重复的组在 postmeta 结果中...我目前仍在寻找纠正此问题的方法。

-- 编辑#3--

这是添加的 MCVE:

-- 原始查询:http://sqlfiddle.com/#!9/386b98/2

-- 更新查询:http://sqlfiddle.com/#!9/386b98/3

【问题讨论】:

见:Why should I provide an MCVE for what seems to me to be a very simple SQL query? @Strawberry - 你是对的 - 我会为所有未来的 sql 问题添加一个 MCVE - 我会尽快在此处添加一个,以便访问者可以看到两者之间的区别查询 【参考方案1】:

出现重复问题是因为我不知道在 SQL 中处理 JOINS 的方式 - (我仍在学习) - 这个堆栈溢出答案真的帮助了我(Martin Smith)sql joins as venn diagram

看起来当它连接user_meta 表的多行数据时,每个post_meta 表行被连接了很多次,反之亦然。所以我目前的解决方案是从这两个表中删除 INNER JOIN 并将它们简单地添加到语句的 SELECT 部分 - 就像这样:

SELECT 
   a.`ID`, a.`post_date`, a.`post_content`, a.`post_title`, 
   a.`post_status`, a.`post_name`, a.`post_type`, a.`post_parent`, 
   (SELECT GROUP_CONCAT(d.`meta_key` SEPARATOR '|') FROM `wp_postmeta` d 
       WHERE d.`post_id` = a.`ID`) AS `post_meta_keys`, 
   (SELECT GROUP_CONCAT(d.`meta_value` SEPARATOR '|') FROM `wp_postmeta` d 
       WHERE d.`post_id` = a.`ID`) AS `post_meta_values`, 
   b.`user_login`, b.`user_pass`, b.`user_nicename`, b.`user_email`, 
   b.`user_registered`, b.`display_name`, 
   (SELECT GROUP_CONCAT(c.`meta_key` SEPARATOR '|') FROM `wp_usermeta` c 
       WHERE c.`user_id` = a.`post_author`) AS `user_meta_keys`, 
   (SELECT GROUP_CONCAT(c.`meta_value` SEPARATOR '|') FROM `wp_usermeta` c 
       WHERE c.`user_id` = a.`post_author`) AS `user_meta_values` 
FROM 
   `wp_posts` a 
INNER JOIN 
   `wp_users` b ON a.`post_author` = b.`ID` 
WHERE 
   `post_type` = 'forum' OR 
   `post_type` = 'topic' OR 
   `post_type` = 'reply' 
GROUP BY a.`ID`

我不知道你能做到这一点 - 这会产生更快/更清晰的结果。

-- 工作示例:http://sqlfiddle.com/#!9/386b98/3

【讨论】:

以上是关于MySQL GROUP_CONCAT 防止不必要的重复的主要内容,如果未能解决你的问题,请参考以下文章

MySQL如何防止字符串截断[重复]

解决mysql中group_concat长度限制的方案

mysql 的group_concat方法

mysql用GROUP_CONCAT合并查询出现乱码?求大神!!!

mysql—group_concat函数

mysql查询结果拼接group_concat