До сих пор было несколько хороших ответов, но я бы применил немного другой метод, весьма похожий на тот, который вы описали изначально
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 ряд на основу песни.Это затем присоединяется к голосованию впоследствии.Я также решил просто суммировать столбец v.votes, так как вы указали, что это 1 или 0, и, следовательно, сумма (v.votes) сложит 1 + 1 + 1 + 0 + 0 = 3 из 5 являются повышающими,в то время как SUM (1-v.vote) будет суммировать 0 + 0 + 0 + 1 + 1 = 2 из 5 являются отрицательными.
Если бы у вас был индекс голосов со столбцами (id_song, голосования), тогда этот индекс будет использоваться для этого, чтобы он даже не попал в таблицу.Аналогично, если у вас есть индекс для Songs_Tags с (id_song, id_tag), тогда эта таблица не будет обработана запросом.
edit добавлено решение с использованием счетчика
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