我有这样的MySQL表格,我想计算每种类型的TOP10:
我想为每个类型,每个曲目和每个艺术家获得TOP10排名。
曲目或艺术家最多可以有2种流派。排名可能相同。只是为了得到LIMIT 2的想法:
genreId | trackId | ranking
---------------------------------
0 1111 100
0 2222 99
1 1111 100
1 2222 99
genreId | artistId | ranking
---------------------------------
0 1111 100
0 2222 99
1 1111 100
1 2222 99
我发现的唯一解决方案是将所有内容都放在一个表格中,然后在页面中限制为10,但是它在大小方面会杀死我的数据库(我的资源有限)。
对于我写过的曲目:
SELECT trackId, genreId, @newRank := SUM(ranking) as ranking
FROM rankings_2016
WHERE timestamp >= ( select unix_timestamp('2016-01-01') )
AND timestamp <= ( select unix_timestamp('2016-12-31') )
GROUP BY trackId, genreId
对于艺术家:
SELECT artistId, genreId, @newRank := SUM(a1.ranking) as ranking
FROM rankings_2016 a1
LEFT JOIN artists_tracks a2
ON a1.trackId = a2.trackId
WHERE timestamp >= ( select unix_timestamp('2016-01-01') )
AND timestamp <= ( select unix_timestamp('2016-12-31') )
GROUP BY artistId, genreId
提前感谢所有提示。
<小时/>
一般逻辑(和接受的回复)需要良好的索引和高性能服务器。
我的案例中的艺术家因错误500而失败,除非我增加了CPU。 一般情况下,用INNER替换LEFT会节省1秒钟。
答案 0 :(得分:0)
考虑相关计数子查询,按艺术家/曲目/流派分组对排名进行排名。然后在外部查询中使用此 rank 计算列来过滤每个分组的前10个:
艺术家排名 (每位艺术家和流派排名前10位)
SELECT main.artistId, main.genreId, main.ranking
FROM
(
SELECT a.artistId, r.genreId, r.ranking,
(SELECT COUNT(*) FROM rankings_2016 subr
LEFT JOIN artists_tracks suba ON subr.trackId = suba.trackId
WHERE suba.artistId = a.artistId
AND subr.genreId = r.genreId
AND subr.ranking >= r.ranking) AS rn
FROM rankings_2016 r
LEFT JOIN artists_tracks a ON r.trackId = a.trackId
WHERE r.timestamp BETWEEN ( select unix_timestamp('2016-01-01') )
AND ( select unix_timestamp('2016-12-31') )
) AS main
WHERE main.rn <= 10
跟踪排名 (每首曲目和流派排名前10位)
SELECT main.trackId, main.genreId, main.ranking
FROM
(
SELECT r.trackId, r.genreId, r.ranking,
(SELECT COUNT(*) FROM rankings_2016 subr
WHERE subr.genreId = r.genreId
AND subr.trackId = r.trackId
AND subr.ranking >= r.ranking) AS rn
FROM rankings_2016 r
WHERE r.timestamp BETWEEN ( select unix_timestamp('2016-01-01') )
AND ( select unix_timestamp('2016-12-31') )
) AS main
WHERE main.rn <= 10