これまでにいくつかの良い答えがありましたが、私はあなたが最初に説明したものと非常に似た少し異なる方法を採用します
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
この場合、サブクエリは、タグ付きの曲を曲ごとに1行に照合する役割を果たします。その後、これは投票に参加します。また、1または0であると示したので、v.votes列を単純に合計することを選択しました。したがって、SUM(v.votes)は1 + 1 + 1 + 0 + 0=5つのうち3つが賛成票です。 SUM(1-v.vote)は合計0 + 0 + 0 + 1 + 1 =5つのうち2つは反対票ですが、
列(id_song、vote)を持つ投票のインデックスがある場合、そのインデックスがこれに使用されるため、テーブルにヒットすることさえありません。同様に、Songs_Tagsに(id_song、id_tag)のインデックスがある場合、そのテーブルはクエリの対象になりません。
編集 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