首页 > 解决方案 > for循环查询中的外连接?

问题描述

我有一个使用Slick的相当复杂的查询,它涉及大量的连接,使用for-comprehension来编写它似乎更优雅。

我知道如果所有连接都是内部连接,这是可能的。例如:

val query = TableA
.join(TableB)
.on(_.tableBId === _.id) // Result is an (a, b) tuple.
.join(TableC)
.on(_._1.tableCId === _.id) // Result is an ((a, b), c) tuple.
.join(TableD)
.on(_._1._1.tableDId === _.id) // Result is an (((a, b), c), d) tuple.
.map {
  case (((a, b), c), d) => (a, b, c, d)
}

可以重写为更加优雅和易于理解的(恕我直言):

val query = for {
  a <- TableA
  b <- TableB
  if(a.tableBId === b.id)
  c <- TableC
  if(a.tableCId === c.id)
  d <- TableD
  if(a.tableDId === d.id)
} yield(a, b, c, d)

如果涉及更多连接,后一种变体也可以很好地扩展。

但是,我不确定如果任何连接是左外连接,这是否可能。假设该TableA.tableDId字段是一个Option[Int]值,而不是一个Int值,因此原始查询现在看起来像这样:

val query = TableA
.join(TableB)
.on(_.tableBId === _.id) // Result is an (a, b) tuple.
.join(TableC)
.on(_._1.tableCId === _.id) // Result is an ((a, b), c) tuple.
.leftJoin(TableD)
.on(_._1._1.tableDId === _.id) // Result is an (((a, b), c), Option[d]) tuple.
.map {
  case (((a, b), c), od) => (a, b, c, od)
}

我怎么能把这个写成for理解?

更新:我在这里Slick outer join with multiple tables上看到了这个问题,但答案并不是特别吸引人,而且已经有 7 年历史了。

标签: scalaslick

解决方案


推荐阅读