Váš druhý dotaz je ve tvaru:
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
Výsledkem vnitřních GROUP BY je (user_id, t.tag)
&(user_id, c.category)
jsou klíče/jedinečné. Kromě toho se nebudu zabývat těmi GROUP BY.
TL;DR Když se připojíte (q1 JOIN q2) ke q3, není to na klíči/UNIQUE jednoho z nich, takže pro každé user_id získáte řádek pro každou možnou kombinaci značky a kategorie. Takže konečná GROUP BY vkládá duplikáty na (user_id, tag) &na (user_id, kategorii) a nevhodně GROUP_CONCATs duplikuje tagy a kategorie na user_id. Správně by bylo (q1 JOIN q2 GROUP BY) JOIN (q1 JOIN q3 GROUP BY), ve kterém jsou všechna spojení na společném klíči/UNIQUE (user_id)
&nedochází k žádné falešné agregaci. I když někdy můžete takovou falešnou agregaci vrátit zpět.
Správný symetrický přístup INNER JOIN:LEFT JOIN q1 &q2--1:many--pak GROUP BY &GROUP_CONCAT (což udělal váš první dotaz); pak samostatně podobně LEFT JOIN q1 &q3--1:many--pak GROUP BY &GROUP_CONCAT; pak INNER JOIN dva výsledky ON user_id--1:1.
Správný přístup k symetrickému skalárnímu poddotazu:VYBERTE GROUP_CONCATs z 1. čtvrtletí jako skalární poddotazy každý s GROUP BY.
Správný kumulativní přístup LEFT JOIN:LEFT JOIN q1 &q2--1:many--pak GROUP BY &GROUP_CONCAT; pak LEFT JOIN that &q3--1:many--pak GROUP BY &GROUP_CONCAT.
Správný přístup, jako je váš 2. dotaz:Nejprve LEFT JOIN q1 &q2--1:many. Pak jste ODEŠLI PŘIPOJIT SE k tomu &q3--many:1:many. Poskytuje řádek pro každou možnou kombinaci značky a kategorie, které se objevují s user_id. Poté, co GROUP BY, vytvoříte GROUP_CONCAT – přes duplicitní (user_id, tag) páry a duplicitní (user_id, category) páry. To je důvod, proč máte duplicitní prvky seznamu. Ale přidání DISTINCT do GROUP_CONCAT dává správný výsledek. (Pro wchiquito komentář uživatele.)
To, co dáváte přednost, je jako obvykle technický kompromis, abyste byli informováni o plánech dotazů a načasování podle skutečných dat / použití / statistiky. vstup a statistiky pro očekávané množství duplikace), načasování skutečných dotazů atd. Jedním z problémů je, zda další řádky přístupu many:1:many JOIN kompenzují úsporu GROUP BY.
-- 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 ;