Reputation: 159
i have been trying to use this particular query to find the top three most used musical keys in songs and show all the songs made using those musical keys so far the problem is that i'm using in operator with a subquery and it doesn't work!! i have read that instead of in using join is preferable but since i haven't used any joins i am not able to use that with the query!! plaeae help!!!
SELECT `Key_Name`,`Song_Title`
FROM `musicalkey_record`,`musical_keys`,`record`
WHERE `record`.`Record_ID`=`musicalkey_record`.`Record_ID`
AND `musical_keys`.`Key_ID`=`musicalkey_record`.`Key_ID`
AND `Key_Name` IN (SELECT `Key_Name` FROM `musicalkey_record`,`musical_keys`,`record`
WHERE `record`.`Record_ID`=`musicalkey_record`.`Record_ID`
AND `musical_keys`.`Key_ID`=`musicalkey_record`.`Key_ID` GROUP BY `Key_Name` ORDER BY
COUNT(`Song_Title`) DESC LIMIT 3) ORDER BY `Key_Name`;
query with joins but without subquery:
SELECT `Key_Name`,`Song_Title` FROM `musical_keys` INNER JOIN `musicalkey_record` ON
`musical_keys`.`Key_ID`=`musicalkey_record`.`Key_ID`
INNER JOIN `record` ON `record`.`Record_ID`=`musicalkey_record`.`Record_ID` AND `
Key_Name` IN ('4F','Circle of fifths','C-Major') ORDER BY `Key_Name`;
Upvotes: 0
Views: 91
Reputation: 94859
I may be wrong, but it seems all those joins are not necessary. You want to count song records per musical key. So join musical_keys with musicalkey_record and count. To get the song names you would have to join with record, too, and use wm_concat to get the song names in one string.
SELECT *
FROM
(
SELECT mk.Key_Name, GROUP_CONCAT(r.Song_Title) as Song_Titles
FROM musical_keys mk
LEFT JOIN musicalkey_record mkr ON mkr.Key_ID = mk.Key_ID
LEFT JOIN record r ON r.Record_ID = mkr.Record_ID
GROUP BY mk.Key_Name
ORDER BY COUNT(*) DESC
LIMIT 3
) dummy
ORDER BY Key_Name;
EDIT: If you want to show all equally ranking records, i.e. at least three, but more if record four or more have the same count as record three, then you would have to get the top three, look up the third place and then select again to get all records with at least that count.
SELECT mk.Key_Name, GROUP_CONCAT(r.Song_Title) as Song_Titles
FROM musical_keys mk
LEFT JOIN musicalkey_record mkr ON mkr.Key_ID = mk.Key_ID
LEFT JOIN record r ON r.Record_ID = mkr.Record_ID
GROUP BY mk.Key_Name
HAVING COUNT(*) >=
(
SELECT MIN(cnt)
FROM
(
SELECT COUNT(*) as cnt
FROM musical_keys mk
LEFT JOIN musicalkey_record mkr ON mkr.Key_ID = mk.Key_ID
GROUP BY mk.Key_Name
ORDER BY COUNT(*) DESC
LIMIT 3
) dummy
)
ORDER BY Key_Name;
I suppose that the Key_Name is unique in musical_keys? Then you can even remove musical_keys from the inner select altogether and only select from musicalkey_record grouping by mkr.Key_ID instead of mk.Key_Name. Thus the query is even shorter.
Upvotes: 0
Reputation: 1269443
This is a simplification of Barmar's approach, reducing the number of joins:
SELECT mk.Key_Name, Song_Title
FROM musicalkey_record mr JOIN
musical_keys mk
ON mk.Key_ID = mr.Key_ID JOIN
record r
ON r.Record_ID = mr.Record_ID JOIN
(SELECT Key_ID
FROM musicalkey_record mr
GROUP BY Key_ID
ORDER BY COUNT(*) DESC
LIMIT 3
) top3
ON mr.Key_ID = top3.Key_ID
ORDER BY mk.Key_Name;
Upvotes: 1
Reputation: 780673
SELECT mk.Key_Name, Song_Title
FROM musicalkey_record AS mr
JOIN musical_keys AS mk ON mk.Key_ID = mr.Key_ID
JOIN record AS r ON r.Record_ID = mr.Record_ID
JOIN (SELECT Key_Name
FROM FROM musicalkey_record AS mr
JOIN musical_keys AS mk ON mk.Key_ID = mr.Key_ID
JOIN record AS r ON r.Record_ID = mr.Record_ID
GROUP BY Key_Name
ORDER BY COUNT(Song_Title) DESC
LIMIT 3) AS top3 ON mk.Key_Name = top3.Key_Name
ORDER BY mk.Key_Name
Upvotes: 0