在查询中使用GROUP_CONCAT无法获得正确的结果

时间:2019-06-05 19:40:09

标签: mysql

我在查询中可以使用7个表:

tb_post, tb_spots, users, td_sports, tb_spot_types, tb_users_sports, tb_post_media

这是我正在使用的查询:

SELECT po.id_post AS id_post, 
po.description_post as description_post,
 sp.id_spot as id_spot, 
po.date_post as date_post,
 u.id AS userid, 
u.user_type As tipousuario, 
u.username AS username, 
spo.id_sport AS sportid, 
spo.sport_icon as sporticon, 
st.logo_spot_type as spottypelogo, 
sp.city_spot AS city_spot, 
sp.country_spot AS country_spot, 
sp.latitud_spot as latitudspot,
 sp.longitud_spot as longitudspot,
 sp.short_name AS spotshortname, 
sp.verified_spot AS spotverificado, 
 u.profile_image AS profile_image,
sp.verified_spot_by as spotverificadopor,
 uv.id AS spotverificador,
 uv.user_type AS spotverificadornivel,
 pm.media_type AS mediatype,
 pm.media_file AS mediafile,

GROUP_CONCAT(tus.user_sport_sport) sportsdelusuario,
GROUP_CONCAT(logosp.sport_icon) sportsdelusuariologos,
GROUP_CONCAT(pm.media_file) mediapost,
GROUP_CONCAT(pm.media_type) mediaposttype

FROM tb_posts po 

LEFT JOIN tb_spots sp ON po.spot_post = sp.id_spot 
LEFT JOIN users u ON po.uploaded_by_post = u.id 
LEFT JOIN tb_sports spo ON sp.sport_spot = spo.id_sport
LEFT JOIN tb_spot_types st ON sp.type_spot = st.id_spot_type
LEFT JOIN users uv ON sp.verified_spot_by = uv.id
LEFT JOIN tb_users_sports tus ON tus.user_sport_user = u.id
LEFT JOIN tb_sports logosp ON logosp.id_sport = tus.user_sport_sport
LEFT JOIN tb_post_media pm  ON pm.media_post = po.id_post 

WHERE po.status = 1
GROUP BY po.id_post,uv.id

我在某些GROUP_CONCAT组中遇到问题:

GROUP_CONCAT(tus.user_sport_sport) sportsdelusuario给了我正确的项目,但重复了,所有项目都重复了两次

GROUP_CONCAT(logosp.sport_icon) sportsdelusuariologos给了我正确的项目,但重复了,所有项目都重复了两次

GROUP_CONCAT(pm.media_file) mediapost给了我正确的物品,但重复了四遍

GROUP_CONCAT(pm.media_type) mediaposttype给了我正确的物品,但重复了四遍

如果需要,我可以将所有表结构放在这里。

2 个答案:

答案 0 :(得分:1)

在查询中加入的多个一对多关系对聚合结果产生乘法影响;标准解决方案是子查询:

您可以更改

GROUP_CONCAT(pm.media_type) mediaposttype
...
LEFT JOIN tb_post_media pm  ON pm.media_post = po.id_post 

pm.mediaposttype
...
LEFT JOIN (
   SELECT media_post, GROUP_CONCAT(media_type) AS mediaposttype 
   FROM tb_post_media 
   GROUP BY media_post
) AS pm ON pm.media_post = po.id_post 

如果tb_post_media很大,并且外部查询中的po.status = 1条件将大大减少子查询的结果,那么值得在子查询中复制原始联接以过滤其结果。

类似地,如果外部查询的结果相对较少,则我在注释中提到的相关版本也可以表现更好。 (如果实际上只使用后者的很少结果,则为每个单独的组计算GROUP_CONCAT()的成本将比为所有一次计算它的成本低。)

答案 1 :(得分:1)

或仅将DISTINCT添加到所有group_concat中,例如GROUP_CONCAT(DISTINCT pm.media_type)