Permintaan kedua Anda dalam bentuk:
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
GROUP BY bagian dalam menghasilkan (user_id, t.tag)
&(user_id, c.category)
menjadi kunci/UNIK. Selain itu, saya tidak akan membahas GROUP BY tersebut.
TL;DR Ketika Anda bergabung (q1 GABUNG q2) ke q3, itu bukan pada kunci/UNIK salah satunya sehingga untuk setiap user_id Anda mendapatkan baris untuk setiap kemungkinan kombinasi tag &kategori. Jadi GROUP BY terakhir memasukkan duplikat per (user_id, tag) &per (user_id, kategori) dan secara tidak tepat GROUP_CONCAT menduplikasi tag &kategori per user_id. Yang benar adalah (q1 JOIN q2 GROUP BY) JOIN (q1 JOIN q3 GROUP BY) di mana semua join berada pada kunci yang sama/UNIQUE (user_id)
&tidak ada agregasi palsu. Meskipun terkadang Anda dapat membatalkan agregasi palsu tersebut.
Pendekatan INNER JOIN simetris yang benar:LEFT JOIN q1 &q2--1:many--then GROUP BY &GROUP_CONCAT (yang dilakukan oleh kueri pertama Anda); kemudian secara terpisah sama LEFT JOIN q1 &q3--1:many--lalu GROUP BY &GROUP_CONCAT; lalu INNER JOIN dua hasil ON user_id--1:1.
Pendekatan subkueri skalar simetris yang benar:PILIH GROUP_CONCAT dari q1 sebagai subkueri skalar masing-masing dengan GROUP BY.
Pendekatan LEFT JOIN kumulatif yang benar:LEFT JOIN q1 &q2--1:many--then GROUP BY &GROUP_CONCAT; lalu KIRI GABUNG itu &q3--1:banyak--lalu GROUP BY &GROUP_CONCAT.
Pendekatan yang benar seperti kueri ke-2 Anda:Anda pertama-tama LEFT JOIN q1 &q2--1:many. Kemudian Anda KIRI GABUNG itu &q3--banyak:1:banyak. Ini memberikan baris untuk setiap kemungkinan kombinasi tag &kategori yang muncul dengan user_id. Kemudian setelah Anda GROUP BY Anda GROUP_CONCAT--over duplikat (user_id, tag) pasangan dan duplikat (user_id, kategori) pasangan. Itulah mengapa Anda memiliki elemen daftar duplikat. Tetapi menambahkan DISTINCT ke GROUP_CONCAT memberikan hasil yang benar. (Per wchiquito komentar.)
Yang Anda sukai adalah seperti biasa tradeoff teknik untuk diinformasikan oleh rencana &waktu kueri, per data/penggunaan/statistik aktual. masukan &statistik untuk jumlah duplikasi yang diharapkan), waktu kueri aktual, dll. Satu masalah adalah apakah baris tambahan dari pendekatan many:1:many JOIN mengimbangi penghematannya dari 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 ;