如何使用Prisma查询获胜场数最多的玩家,无原生方案时如何用SQL高效实现
Prisma查询获胜场数最多的玩家实现方案
你提到的原有方案确实存在性能问题,全量拉取数据到应用层处理会随着数据量增长出现明显的内存占用过高、执行效率低的问题,以下是两种更优的实现方案:
方案1:Prisma原生实现(推荐)
Prisma 4.0及以上版本支持关联模型计数、排序能力,所有计算逻辑都在数据库层完成,无需手动处理数据:
const topWinPlayer = await prisma.player.findMany({ // 按获胜场数倒序排序 orderBy: { game: { _count: "desc" } }, // 过滤出至少有一场获胜的玩家,可按需删除 where: { game: { some: { isWin: true } } }, // 额外返回获胜场数字段,可按需保留 include: { _count: { select: { game: { where: { isWin: true } } } } }, // 取排名第一的玩家,如需处理并列第一可调整take的数值 take: 1 })
该方案性能和原生SQL基本一致,同时保留了Prisma的类型提示能力。
方案2:Raw SQL最高效实现
如果使用的Prisma版本不支持上述关联计数语法,可以直接执行原生SQL,性能最优:
SELECT p.id, p.name, COUNT(g.id) AS win_count FROM Player p INNER JOIN Game g ON p.id = g.playerId WHERE g.isWin = true GROUP BY p.id, p.name ORDER BY win_count DESC LIMIT 1;
对应Prisma调用代码:
const topWinPlayer = await prisma.$queryRaw` SELECT p.id, p.name, COUNT(g.id) AS win_count FROM Player p INNER JOIN Game g ON p.id = g.playerId WHERE g.isWin = true GROUP BY p.id, p.name ORDER BY win_count DESC LIMIT 1; `
该SQL语法兼容PostgreSQL、MySQL等主流数据库,只需要给Game表的playerId和isWin字段加联合索引,就能实现毫秒级查询,哪怕数据量达到百万级也不会有性能问题。
内容的提问来源于stack exchange,提问作者Danila
相关产品推荐
相关产品推荐

