2014-01-28 31 views
2

我想执行与油滑执行SQL如下所示的聚合:骨料的多个列中油滑2.0

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

其中table_a具有INTa

在油滑给出的表定义:

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. 写类似:

    as 
        .groupBy(_ => 1) 
        .map { case (_, as) => (as.map(identity).min, as.map(identity).max) } 
    

但是,生成的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

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

作为一种解决方法,这里是引擎盖下换出生成的SQL,离开一切不变的模式:https://gist.github.com/cvogt/8054159

+0

好的,谢谢。对于Postgres,事实证明'as.groupBy(_ => true)...'产生了'SELECT ... GROUP BY true',这是有效的,尽管我怀疑它适用于所有的DBMS。 – kong

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表达技巧的使用变量的编译器,以为可以有多个组。