我想与Slick执行聚合,执行SQL,如下所示:
SELECT MIN(a), MAX(a) FROM table_a;
其中table_a
有一个INT
列a
在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)
似乎我有两个选择:
写出类似:Query(as.min, as.max)
写下类似的内容:
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
的聚合中发出单个查询?
答案 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
表达式中使用变量会让编译器误以为可能有多个组。