如何使用Slick进行聚合

27
我想强制Slick创建类似于查询的内容
select max(price) from coffees where ... 

但是Slick的文档没有帮助。
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代替”)。 如何在没有警告的情况下生成这样的查询?

另一个问题是按组进行聚合:

"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个回答

31
据我所知,第一个只是简单的。
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

4
可以使用 .first 替代 .list.head,如果我没记错的话。 - user500592
谢谢,我在答案中进行了更改。 - EECOLOR
谢谢,两个例子都可以工作,第二个生成了最优查询“select x2."COF_NAME", max(x2."PRICE") from "coffees" x2 group by x2."COF_NAME"”,但第一个生成了带有2个子查询的查询“select x2.x3 from (select max(x4.x5) as x3 from (select x6."PRICE" as x5 from "coffees" x6) x4) x2”,而不是由已弃用的API生成的简单查询“select max(x2."PRICE") from "coffees" x2"。看起来Slick开发人员过早地弃用了这个API。 - Jeriho
1
注意:在Slick2中需要使用run方法而不是list/first,请参见http://stackoverflow.com/questions/23830960/slick-2-aggregation-how-to-get-a-scalar-result/23831610?noredirect=1#23831610。 - Suma

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接