如何在Python中实现MySQL按流派返回Top N条查询记录?
如何实现MySQL每个流派仅显示Top N条记录?
你的当前代码确实能按流派和演员参演电影数量排序,但没有对每个流派的结果做条数限制,所以返回了6000+条全量记录。要实现每个流派只取Top N个演员(按参演电影数降序),我给你两种实用的解决方案,适配不同版本的MySQL:
方案一:使用窗口函数(MySQL 8.0+ 推荐)
MySQL 8.0及以上支持窗口函数,用ROW_NUMBER()可以轻松给每个流派内的记录排序并编号,然后筛选出前N条。修改后的SQL更简洁规范:
SELECT genre_name, actor_id, num_mov FROM ( SELECT g.genre_name, a.actor_id, COUNT(mg.genre_id) AS num_mov, -- 按流派分组,组内按参演电影数降序排,生成序号 ROW_NUMBER() OVER (PARTITION BY g.genre_id ORDER BY COUNT(mg.genre_id) DESC) AS rn FROM actor AS a JOIN role AS r ON a.actor_id = r.actor_id JOIN movie AS m ON m.movie_id = r.movie_id JOIN movie_has_genre AS mg ON m.movie_id = mg.movie_id JOIN genre AS g ON g.genre_id = mg.genre_id GROUP BY g.genre_id, g.genre_name, a.actor_id ) AS ranked -- 只保留每个流派的前N条 WHERE rn <= %s ORDER BY genre_name, num_mov DESC
对应Python代码修改:
把原代码里的cur.execute(sql)改成带参数的执行方式(避免SQL注入风险):
cur.execute(sql, (n,))
另外,原代码里的con.commit()可以删掉,因为查询操作不需要提交事务。
方案二:使用用户变量(兼容MySQL 5.x版本)
如果你的MySQL版本低于8.0,不支持窗口函数,可以用用户变量模拟分组排序的逻辑:
SELECT genre_name, actor_id, num_mov FROM ( SELECT g.genre_name, a.actor_id, COUNT(mg.genre_id) AS num_mov, -- 用变量跟踪当前流派,重置序号 @rn := IF(@current_genre = g.genre_id, @rn + 1, 1) AS rn, @current_genre := g.genre_id FROM actor AS a JOIN role AS r ON a.actor_id = r.actor_id JOIN movie AS m ON m.movie_id = r.movie_id JOIN movie_has_genre AS mg ON m.movie_id = mg.movie_id JOIN genre AS g ON g.genre_id = mg.genre_id -- 初始化变量 CROSS JOIN (SELECT @current_genre := '', @rn := 0) AS vars GROUP BY g.genre_id, g.genre_name, a.actor_id ORDER BY g.genre_id, num_mov DESC ) AS ranked WHERE rn <= %s ORDER BY genre_name, num_mov DESC
同样,Python执行部分用参数传递n即可。
这样修改后,你的查询就只会返回每个流派中参演电影数量最多的前N个演员,结果集大小会大幅缩减。
内容的提问来源于stack exchange,提问作者Salih K. Chousein
相关产品推荐
相关产品推荐

