如何使用 slick 进行聚合

Posted

技术标签:

【中文标题】如何使用 slick 进行聚合【英文标题】:How to make aggregations with slick 【发布时间】:2013-02-17 22:06:39 【问题描述】:

我想强制 slick 创建像

这样的查询
select max(price) from coffees where ... 

但是slick's documentation 没有帮助

val q = Coffees.map(_.price) //this is query Query[Coffees.type, ...]
val q1 = q.min // this is Column[Option[Double]]
val q2 = q.max
val q3 = q.sum
val q4 = q.avg 

因为那些 q1-q4 不是查询,所以我无法获得结果,但可以在其他查​​询中使用它们。

此声明

for 
  coffee <- Coffees
 yield coffee.price.max

生成正确的查询但不推荐使用(生成警告:“不推荐使用类 ColumnExtensionMethods 中的方法 max:改用 Query.max”)。 如何在没有警告的情况下生成这样的查询?

另一个问题是与 group by 聚合:

"select name, max(price) from coffees group by name"

试图解决它

for 
  coffee <- Coffees
 yield (coffee.name, coffee.price.max)).groupBy(x => x._1)

生成

select x2.x3, x2.x3, x2.x4 from (select x5."COF_NAME" as x3, max(x5."PRICE") as x4 from "coffees" x5) x2 group by x2.x3

导致明显的数据库错误

column "x5.COF_NAME" must appear in the GROUP BY clause or be used in an aggregate function

如何生成这样的查询?

【问题讨论】:

【参考方案1】:

据我所知是第一个简单

Query(Coffees.map(_.price).max).first

第二个

val maxQuery = Coffees
  .groupBy  _.name 
  .map  case (name, c) =>
    name -> c.map(_.price).max
  

maxQuery.list

val maxQuery = for 
  (name, c) <- Coffees groupBy (_.name)
 yield name -> c.map(_.price).max

maxQuery.list

【讨论】:

你可以用 .list.head 代替 .first, IIRC 谢谢,我在答案里改了 谢谢,这两个例子都有效,第二个生成最优查询 "select x2."COF_NAME", max(x2."PRICE") from "coffees" x2 group by x2."COF_NAME"",但是第一个生成“select x2.x3 from (select max(x4.x5) as x3 from (select x6."PRICE" as x5 from "coffees" x6) x4) x2” - 使用 2 个子查询而不是简单的“select max”查询(x2."PRICE") 来自不推荐使用的 api 生成的 "coffees" x2"。似乎聪明的开发人员过早地弃用了这个 api。 注意:在 Slick2 中需要 run 方法而不是 list/first,参见***.com/questions/23830960/…

以上是关于如何使用 slick 进行聚合的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 slick 创建数据库

如何使用数据属性更改 Slick Slider 默认箭头?

如何使用嵌套元组或 HList 处理具有 Slick 的 > 22 列表?

如何在 SLICK 中使用 SQL“LIKE”运算符

Slick 3 - 如何在使用纯 SQL 插入时获得正确的(数据库)架构

Slick:如何将 SQL LIKE 语句与 SQL IN 语句结合使用