MySQL GROUP_CONCAT 防止不必要的重复

MySQL GROUP_CONCAT prevent unnecessary duplicates

我正在从本地 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`

我正在尝试获得一个大视图,其中每一行都有 Post、它的元信息和它的作者信息。一切都很好,除了 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 列有这么多重复项,如果查询写错了 - 我至少会计算出 'keys' 列和'values' 列 - 但它们也没有。

2) 能否调整查询以完成我正在寻找的内容?

感谢您的宝贵时间!

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

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

-- 编辑#3--

这是一个添加的 MCVE:

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

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

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

看起来当它连接 user_meta table 的多行数据时,每个 post_meta table 行连接了很多次,反之亦然反之亦然。所以我目前的解决方案是从这两个 table 中删除 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