Det har funnits några bra svar hittills, men jag skulle använda en lite annorlunda metod som liknar det du beskrev från början
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
I denna är underfrågan ansvarig för att sammanställa låtar med taggar i en rad per låt. Detta sammanfogas sedan till Votes efteråt. Jag valde också att helt enkelt summera kolumnen v.votes eftersom du har angett att den är 1 eller 0 och därför kommer en SUM(v.votes) att summera 1+1+1+0+0 =3 av 5 är uppröster, medan SUM(1-v.röst) kommer att summera 0+0+0+1+1 =2 av 5 är nedröster.
Om du hade ett index på röster med kolumnerna (id_song,vote) så skulle det indexet användas för detta så att det inte ens skulle hamna i bordet. På samma sätt om du hade ett index på Songs_Tags med (id_song,id_tag) så skulle den tabellen inte träffas av frågan.
redigera tillagd lösning med hjälp av 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