Rumah >pangkalan data >tutorial mysql >Bagaimana untuk Mengelakkan Pendua dalam `GROUP_CONCAT` Apabila Menyertai Berbilang `GROUP_BY`?

Bagaimana untuk Mengelakkan Pendua dalam `GROUP_CONCAT` Apabila Menyertai Berbilang `GROUP_BY`?

Linda Hamilton
Linda Hamiltonasal
2025-01-18 06:16:09310semak imbas

How to Avoid Duplicates in `GROUP_CONCAT` When Joining Multiple `GROUP_BY`s?

Mengatasi Keputusan Pendua dalam GROUP_CONCAT dengan Berbilang GROUP BY Gabungan

Menggabungkan berbilang GROUP BY klausa melalui LEFT JOINs dan menggunakan GROUP_CONCAT boleh membawa kepada pendua entri. Ini timbul daripada penggabungan kunci unik daripada setiap GROUP BY, mengakibatkan perwakilan data yang tidak tepat.

Senario Masalah

Pertimbangkan struktur pertanyaan ini:

<code class="language-sql">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,
    SUBSTRING_INDEX(GROUP_CONCAT(q3.category ORDER BY q3.category_reputation DESC SEPARATOR ','), ',', 2) AS category
FROM
    (...) AS q1
    LEFT JOIN (...) AS q2 ON q2.user_id = q1.user_id 
    LEFT JOIN (...) AS q3 ON q3.user_id = q1.user_id 
GROUP BY
    q1.user_id, q1.user_name, q1.score, q1.reputation</code>

Pertanyaan ini bertujuan untuk mendapatkan semula dua teg dan kategori teratas untuk setiap pengguna, dengan mengandaikan jadual untuk pengguna, teg, reputasi, post_tag, kategori dan post_category. Masalahnya ialah potensi pendua seperti "css,css" atau "technology,technology" disebabkan oleh GROUP BYs yang digabungkan.

Penyelesaian Berkesan

Beberapa kaedah boleh menghalang pendua ini:

1. Asingkan GROUP BY dan SERTAI DALAM:

<code class="language-sql">-- Separate grouping and joining approach
SELECT
    q1.user_id, q1.user_name, q1.score, q1.reputation, q1.top_two_tags, q2.category
FROM
    (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
        (...) AS q1
        LEFT JOIN (...) AS q2 ON q2.user_id = q1.user_id 
    GROUP BY
        q1.user_id, q1.user_name, q1.score, q1.reputation
    ) AS q1
    INNER JOIN
    (SELECT
        q1.user_id, 
        SUBSTRING_INDEX(GROUP_CONCAT(q3.category ORDER BY q3.category_reputation DESC SEPARATOR ','), ',', 2) AS category
    FROM
        (...) AS q1
        LEFT JOIN (...) AS q3 ON q3.user_id = q1.user_id 
    GROUP BY
        q1.user_id
    ) AS q2
    ON q1.user_id = q2.user_id;</code>

Kaedah ini mula-mula mengumpulkan dan menggabungkan teg dan kategori secara berasingan, kemudian menggabungkan hasil menggunakan INNER JOIN pada user_id. Ini memastikan hanya satu baris bagi setiap pengguna dihasilkan.

2. Subqueries Skalar:

<code class="language-sql">-- Scalar subquery approach
SELECT
    q1.user_id, q1.user_name, q1.score, q1.reputation,
    (SELECT
        SUBSTRING_INDEX(GROUP_CONCAT(q2.tag ORDER BY q2.tag_reputation DESC SEPARATOR ','), ',', 2)
    FROM (...) AS q2
    WHERE q2.user_id = q1.user_id
    ),
    (SELECT
        SUBSTRING_INDEX(GROUP_CONCAT(q3.category ORDER BY q3.category_reputation DESC SEPARATOR ','), ',', 2)
    FROM (...) AS q3
    WHERE q3.user_id = q1.user_id
    )
FROM
    (...) AS q1;</code>

Ini menggunakan subkueri dalam senarai SELECT untuk mengambil teg dan kategori teratas bagi setiap pengguna secara individu, mengelakkan kekaburan GROUP BY.

Kuncinya adalah untuk mengelak daripada menggabungkan data secara langsung daripada berbilang jadual yang digabungkan dalam satu panggilan GROUP_CONCAT apabila menggunakan GROUP BY pada berbilang jadual. Penyelesaian yang dipilih bergantung pada struktur pangkalan data khusus dan pertimbangan prestasi. Matlamatnya adalah untuk menghasilkan keputusan yang tepat dan bebas pendua.

Atas ialah kandungan terperinci Bagaimana untuk Mengelakkan Pendua dalam `GROUP_CONCAT` Apabila Menyertai Berbilang `GROUP_BY`?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn