Truy vấn thứ hai của bạn có dạng:
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
Các GROUP BY bên trong dẫn đến (user_id, t.tag)
&(user_id, c.category)
là khóa / DUY NHẤT. Ngoài ra, tôi sẽ không giải quyết các GROUP BY đó.
TL; DR Khi bạn nối (q1 JOIN q2) với q3, nó không nằm trên một khóa / DUY NHẤT của một trong số chúng, vì vậy đối với mỗi user_id, bạn nhận được một hàng cho mọi kết hợp thẻ &danh mục có thể có. Vì vậy, GROUP BY cuối cùng nhập các thẻ &danh mục trùng lặp cho mỗi (user_id, tag) &per (user_id, category) và các thẻ &danh mục trùng lặp không thích hợp GROUP_CONCAT cho mỗi user_id. Đúng sẽ là (q1 JOIN q2 GROUP BY) JOIN (q1 JOIN q3 GROUP BY) trong đó tất cả các liên kết đều nằm trên khóa chung / UNIQUE (user_id)
&không có tập hợp giả mạo. Mặc dù đôi khi bạn có thể hoàn tác tập hợp giả mạo như vậy.
Cách tiếp cận INNER JOIN đối xứng đúng:LEFT JOIN q1 &q2--1:many - sau đó GROUP BY &GROUP_CONCAT (đó là những gì truy vấn đầu tiên của bạn đã làm); sau đó riêng biệt tương tự LEFT JOIN q1 &q3--1:many - sau đó GROUP BY &GROUP_CONCAT; sau đó INNER THAM GIA hai kết quả BẬT user_id - 1:1.
Cách tiếp cận truy vấn con vô hướng đối xứng đúng:CHỌN GROUP_CONCATs từ q1 là truy vấn con vô hướng mỗi người có một GROUP BY.
Cách tiếp cận LEFT JOIN tích lũy đúng:LEFT JOIN q1 &q2--1:many - then GROUP BY &GROUP_CONCAT; sau đó THAM GIA TRÁI &q3--1:nhiều - sau đó NHÓM THEO &GROUP_CONCAT.
Một cách tiếp cận đúng như truy vấn thứ 2 của bạn:Đầu tiên bạn TRÁI THAM GIA q1 &q2--1:many. Sau đó, bạn THAM GIA TRÁI mà &q3 - nhiều:1:nhiều. Nó cung cấp một hàng cho mọi kết hợp có thể có của thẻ &danh mục xuất hiện với user_id. Sau đó, sau khi bạn GROUP BY bạn GROUP_CONCAT - qua các cặp trùng lặp (user_id, tag) và các cặp trùng lặp (user_id, category). Đó là lý do tại sao bạn có các phần tử danh sách trùng lặp. Nhưng thêm DISTINCT vào GROUP_CONCAT sẽ cho kết quả chính xác. (Theo wchiquito nhận xét của.)
Như thường lệ, bạn thích đánh đổi kỹ thuật để được thông báo bằng kế hoạch và thời gian truy vấn, theo dữ liệu thực tế / sử dụng / thống kê. đầu vào &số liệu thống kê cho lượng trùng lặp dự kiến), thời gian của các truy vấn thực tế, v.v. Một vấn đề là liệu các hàng bổ sung của phương pháp tiếp cận many:1:many có bù đắp cho việc tiết kiệm được một GROUP BY hay không.
-- 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 ;