Scala Slick 将 Rep 子查询组合成一个 re

Posted

技术标签:

【中文标题】Scala Slick 将 Rep 子查询组合成一个 re【英文标题】:Scala Slick combining Rep sub queries into one re 【发布时间】:2020-01-25 19:14:26 【问题描述】:

我总结了两个不同数据库表中的总数:

val sum1Query: Rep[Int] = tableQuery1.map(_.amount).sum.ifNull(0)
val sum2Query: Rep[Int] = tableQuery2.map(_.amount).sum.ifNull(0)

for 
  sum1 <- sum1Query.result
  sum2 <- sum2Query.result
 yield 
  sum1 + sum2

这会在每次调用 .result 时对数据库运行 2 个 SQL 查询。我正在寻找一种让它只使用一个 SQL 查询的方法。

这样的事情是行不通的:

for 
  sum1 <- sum1Query
  sum2 <- sum2Query
 yield 
  sum1 + sum2
.result

除了使用普通的 SQL 查询之外,关于如何在 Slick 中执行此操作的任何想法?

【问题讨论】:

可能的解决方案是将其包装在返回一行的查询中: tableQuery3.filter(_.id === 1).map _ => sum1 + sum2 .result.headOption 但会喜欢找到更好看的东西。 【参考方案1】:

.result 的每次调用都会创建一个DBIO 操作,这是一条SQL 语句。减少操作数量的技巧是找到一种方法将两个查询(或两个Reps)组合成一个操作。

在您的情况下,您可以压缩两个查询:

val sum1 = table1.map(_.amount).sum.ifNull(0)
val sum2 = table2.map(_.amount).sum.ifNull(0)
val query = sum1.zip(sum2)

运行query.result 时,您将执行一个查询,例如:

select ifnull(x2.x3,0), ifnull(x4.x5,0) 
from 
  (select sum("amount") as x3 from "table_1") x2, 
  (select sum("amount") as x5 from "table_2") x4

...这将导致两个值的元组。

但是,由于您已经获得了 Rep[Int],您可以在数据库中使用 +

val query = sum1 + sum2

...这将是一个查询:

select ifnull(x2.x3,0) + ifnull(x4.x5,0) 
from 
 (select sum("amount") as x3 from "table_1") x2, 
 (select sum("amount") as x5 from "table_2") x4

【讨论】:

【参考方案2】:

这样说吧:

(sum1 + sum2).result

【讨论】:

以上是关于Scala Slick 将 Rep 子查询组合成一个 re的主要内容,如果未能解决你的问题,请参考以下文章

可以使用子查询将这些查询组合成一个吗?

将多个子查询组合成一个查询

将 Scala Slick 与数据库枚举一起使用

将 scala 数据框列组合成单个案例类

在 Slick 3.1.1 中比较日期

Spark Streaming Scala 将不同结构的 json 组合成一个 DataFrame