Mysql
 sql >> Datenbank >  >> RDS >> Mysql

LEFT JOIN nach GROUP BY?

Bisher gab es einige gute Antworten, aber ich würde eine etwas andere Methode anwenden, die der von Ihnen ursprünglich beschriebenen ziemlich ähnlich ist

SELECT
    songsWithTags.*,
    COALESCE(SUM(v.vote),0) AS votesUp,
    COALESCE(SUM(1-v.vote),0) AS votesDown
FROM (
    SELECT
        s.*,
        COLLATE(GROUP_CONCAT(st.id_tag),'') AS tags_ids
    FROM Songs s
    LEFT JOIN Songs_Tags st
        ON st.id_song = s.id
    GROUP BY s.id
) AS songsWithTags
LEFT JOIN Votes v
ON songsWithTags.id = v.id_song

GROUP BY songsWithTags.id DESC

Dabei ist die Unterabfrage dafür verantwortlich, Songs mit Tags in einer Basis von 1 Zeile pro Song zu sortieren. Dies wird dann später mit Votes verbunden. Ich habe mich auch dafür entschieden, die v.votes-Spalte einfach zusammenzufassen, da Sie angegeben haben, dass sie 1 oder 0 ist, und daher ergibt eine SUM(v.votes) 1 + 1 + 1 + 0 + 0 =3 von 5 sind positive Stimmen. während SUM(1-v.vote) 0+0+0+1+1 summiert =2 von 5 sind Downvotes.

Wenn Sie einen Index für Stimmen mit den Spalten (id_song,vote) hätten, würde dieser Index dafür verwendet, sodass er nicht einmal in die Tabelle eindringt. Wenn Sie einen Index für Songs_Tags mit (id_song,id_tag) hätten, würde diese Tabelle von der Abfrage nicht getroffen.

bearbeiten hinzugefügte Lösung mit count

SELECT
    songsWithTags.*,
    COUNT(CASE WHEN v.vote=1 THEN 1 END) as votesUp,
    COUNT(CASE WHEN v.vote=0 THEN 1 END) as votesDown
FROM (
    SELECT
        s.*,
        COLLATE(GROUP_CONCAT(st.id_tag),'') AS tags_ids
    FROM Songs s
    LEFT JOIN Songs_Tags st
        ON st.id_song = s.id
    GROUP BY s.id
) AS songsWithTags
LEFT JOIN Votes v
ON songsWithTags.id = v.id_song

GROUP BY songsWithTags.id DESC