在Slick 2.0中聚合多个列而不使用Group By

时间:2014-01-28 18:59:36

标签: sql scala slick

我想与Slick执行聚合,执行SQL,如下所示:

SELECT MIN(a), MAX(a) FROM table_a;

其中table_a有一个INTa

在Slick中给出了表定义:

class A(tag: Tag) extends Table[Int](tag, "table_a") { 
  def a = column[Int]("a")
  def * = a 
}
val A = TableQuery[A]
val as = A.map(_.a)

似乎我有两个选择:

  1. 写出类似:Query(as.min, as.max)

  2. 的内容
  3. 写下类似的内容:

    as
      .groupBy(_ => 1)
      .map { case (_, as) => (as.map(identity).min, as.map(identity).max) }
    
  4. 但是,在任何一种情况下生成的sql都不好。在1中,生成了两个单独的子选择,这就像编写两个单独的查询。在2中,生成以下内容:

    select min(x2."a"), max(x2."a") from "table_a" x2 group by 1
    

    但是,这种语法对于Postgres是不正确的(它按第一列值分组,在这种情况下无效)。实际上AFAIK不可能在Postgres中按常数值分组,除非省略group by子句。

    有没有办法让Slick在没有GROUP BY的聚合中发出单个查询?

2 个答案:

答案 0 :(得分:2)

语法错误是一个错误。我创建了一张票:https://github.com/slick/slick/issues/630 子查询是Slick的SQL编译器的限制,目前在这种情况下产生非最佳代码。我们正在努力改善这种状况。

作为一种解决方法,这里有一个模式来交换生成的SQL,并保留其他所有内容:https://gist.github.com/cvogt/8054159

答案 1 :(得分:0)

我在SQL Server中使用以下技巧,它似乎适用于Postgres:

select min(x2."a"), max(x2."a")
from "table_a" x2
group by (case when x2.a = x2.a then 1 else 1 end);

group by表达式中使用变量会让编译器误以为可能有多个组。