Uw tweede vraag is van de vorm:
q1 -- PK user_id
LEFT JOIN (...
GROUP BY user_id, t.tag
) AS q2
ON q2.user_id = q1.user_id
LEFT JOIN (...
GROUP BY user_id, c.category
) AS q3
ON q3.user_id = q1.user_id
GROUP BY -- group_concats
De binnenste GROUP BY's resulteren in (user_id, t.tag)
&(user_id, c.category)
sleutels/UNIEK zijn. Verder ga ik niet in op die GROUP BY's.
TL;DR Wanneer je (q1 JOIN q2) aan q3 toevoegt, is het niet op een sleutel/UNIEK van een van hen, dus voor elke user_id krijg je een rij voor elke mogelijke combinatie van tag en categorie. Dus de laatste GROUP BY voert duplicaten in per (user_id, tag) &per (user_id, categorie) en ongepast GROUP_CONCATs dubbele tags en categorieën per user_id. Correct zou zijn (q1 JOIN q2 GROUP BY) JOIN (q1 JOIN q3 GROUP BY) waarin alle joins op een gemeenschappelijke sleutel staan/UNIEKE (user_id)
&er is geen valse aggregatie. Hoewel je zo'n valse samenvoeging soms ongedaan kunt maken.
Een correcte symmetrische INNER JOIN-aanpak:LEFT JOIN q1 &q2--1:many--dan GROUP BY &GROUP_CONCAT (wat je eerste query deed); dan afzonderlijk op dezelfde manier LEFT JOIN q1 &q3--1:many--dan GROUP BY &GROUP_CONCAT; dan BINNEN DE twee resultaten OP user_id--1:1.
Een correcte symmetrische scalaire subquerybenadering:SELECTEER de GROUP_CONCAT's van q1 als scalar subquery's elk met een GROUP BY.
Een correcte cumulatieve LEFT JOIN-benadering:LEFT JOIN q1 &q2--1:many--dan GROUP BY &GROUP_CONCAT; dan LEFT JE AAN dat &q3--1:many--dan GROUP BY &GROUP_CONCAT.
Een correcte benadering zoals uw 2e vraag:U gaat eerst LEFT JOIN q1 &q2--1:many. Dan ga je LEFT JOIN dat &q3--veel:1:veel. Het geeft een rij voor elke mogelijke combinatie van een tag &een categorie die verschijnen met een user_id. Nadat u GROUP DOOR u GROUP_CONCAT--over dubbele (user_id, tag) paren en dubbele (user_id, categorie) paren. Daarom heb je dubbele lijstelementen. Maar het toevoegen van DISTINCT aan GROUP_CONCAT geeft een correct resultaat. (Per wchiquito 's commentaar.)
Waar u de voorkeur aan geeft, is zoals gewoonlijk een technische afweging die moet worden gemaakt door queryplannen en -tijden, per werkelijke gegevens/gebruik/statistieken. invoer en statistieken voor de verwachte hoeveelheid duplicatie), timing van daadwerkelijke zoekopdrachten, enz. Een probleem is of de extra rijen van de many:1:many JOIN-benadering de besparing van een GROUP BY compenseerde.
-- cumulative LEFT JOIN approach
SELECT
q1.user_id, q1.user_name, q1.score, q1.reputation,
top_two_tags,
substring_index(group_concat(q3.category ORDER BY q3.category_reputation DESC SEPARATOR ','), ',', 2) AS category
FROM
-- your 1st query (less ORDER BY) AS q1
(SELECT
q1.user_id, q1.user_name, q1.score, q1.reputation,
substring_index(group_concat(q2.tag ORDER BY q2.tag_reputation DESC SEPARATOR ','), ',', 2) AS top_two_tags
FROM
(SELECT
u.id AS user_Id,
u.user_name,
coalesce(sum(r.score), 0) as score,
coalesce(sum(r.reputation), 0) as reputation
FROM
users u
LEFT JOIN reputations r
ON r.user_id = u.id
AND r.date_time > 1500584821 /* unix_timestamp(DATE_SUB(now(), INTERVAL 1 WEEK)) */
GROUP BY
u.id, u.user_name
) AS q1
LEFT JOIN
(
SELECT
r.user_id AS user_id, t.tag, sum(r.reputation) AS tag_reputation
FROM
reputations r
JOIN post_tag pt ON pt.post_id = r.post_id
JOIN tags t ON t.id = pt.tag_id
WHERE
r.date_time > 1500584821 /* unix_timestamp(DATE_SUB(now(), INTERVAL 1 WEEK)) */
GROUP BY
user_id, t.tag
) AS q2
ON q2.user_id = q1.user_id
GROUP BY
q1.user_id, q1.user_name, q1.score, q1.reputation
) AS q1
-- finish like your 2nd query
LEFT JOIN
(
SELECT
r.user_id AS user_id, c.category, sum(r.reputation) AS category_reputation
FROM
reputations r
JOIN post_category ct ON ct.post_id = r.post_id
JOIN categories c ON c.id = ct.category_id
WHERE
r.date_time > 1500584821 /* unix_timestamp(DATE_SUB(now(), INTERVAL 1 WEEK)) */
GROUP BY
user_id, c.category
) AS q3
ON q3.user_id = q1.user_id
GROUP BY
q1.user_id, q1.user_name, q1.score, q1.reputation
ORDER BY
q1.reputation DESC, q1.score DESC ;