查找按其关系的聚合属性排序的实体

Posted

技术标签:

【中文标题】查找按其关系的聚合属性排序的实体【英文标题】:Find entities sorted by aggregated property of their relations 【发布时间】:2021-10-05 02:34:59 【问题描述】:

问题与Find entity with most relations filtered by criteria 非常相似,但略有不同。

model Player 
  id   String @id
  name String @unique
  game Game[]


model Game 
  id       String   @id
  isWin    Boolean
  playerId String
  player   Player   @relation(fields: [playerId], references: [id])

我想找出胜率最高的 10 位玩家(isWin=true 的游戏数除以该玩家的游戏总数)。

直接而缓慢的方法是找到至少赢过一次的所有玩家并计算他们的胜利(第一次查询)。然后为他们每个人计算他们的游戏总数(第二个查询)。然后在应用程序端进行数学运算和排序,同时将结果保存在内存中。

有没有更简单的方法来做到这一点?我将如何使用prisma 做到这一点?如果没有 prisma “本机”方式来做到这一点,那么使用原始 SQL 最有效的方式是什么?

【问题讨论】:

【参考方案1】:

这是简单的聚合:

SELECT p.id, p.name
     , COUNT(CASE WHEN isWin THEN 1 END) AS wins
     , COUNT(g.playerId) AS played
     , 100 * COUNT(CASE WHEN isWin THEN 1 END)
           / COUNT(g.playerId) AS rate
  FROM player AS p
  JOIN game   AS g
    ON g.playerId = p.id
 GROUP BY p.name         -- since p.name is unique, not the id.
 ORDER BY rate DESC
 LIMIT 10
;

根据您的数据库的需要进行调整。我调整了连接变成 LEFT JOIN 的情况,以处理没有玩过游戏的玩家。

PG 的可执行示例,如下面的 cmets 所示。 Working test case - no data

【讨论】:

这给了我一个错误关系“玩家”不存在。提供有关我的表格的更多信息会有所帮助吗?就像它们在原始 sql 或其他东西中的样子 根据您的数据库要求调整表的名称。某些标识符将区分大小写或需要在某些数据库中引用。例如,对于您的数据库,Player 可能与 player 不同,“Player”可能与 Player 不同(不带引号)。 我正在使用 Postgres,尝试了不同的方法,仍然有错误。另外,winsplayed 在您的回答中未使用,这是故意还是错字? 你能以可执行的形式展示你的 postgresql 测试用例吗?请参阅:dbfiddle.uk 以获取显示测试用例的简单方法。这是我上面展示的带有 SQL 的初始测试用例。根据需要调整此测试用例以显示您的问题:https://dbfiddle.uk/?rdbms=postgres_13&fiddle=f9e11b569d4a8c5203625169d535679d 是的。未使用的派生列仅用于显示费率计算中使用的子表达式。

以上是关于查找按其关系的聚合属性排序的实体的主要内容,如果未能解决你的问题,请参考以下文章

为啥聚合+排序比mongo中的查找+排序更快?

如何运用领域驱动设计 - 聚合

使用 NSPredicate 中的聚合函数检查 BOOL 值

如何运用领域驱动设计 - 聚合

对象关系之聚合关系

MongoDB,如何将查找和排序与聚合中的 $cond 结合起来?