Scala Slick:除了join之外怎么做(左外连接是null)?

问题描述 投票:0回答:1

我正在使用scala 2.11,slick 2.1.0和postgres 9.6。主要版本升级是不可能的。

我有2个相同的表(从相同的模型创建),我想做一个除了连接(左外连接为null):except join

我的模型看起来像这样:

trait Coffee {
  val coffeeLoversId:         Option[Int]
  val taxId:                  Option[Long]
  val internationalCoffeeId:  String
  val providerId:             String
}

class Coffees(tag: Tag, schema: String) extends Table[Coffee](tag, Some(schema), "coffees")

  val coffeeLoversId: Column[Option[Int]] = column[Option[Int]]("coffee_lovers_id")
  val taxId: Column[Option[Long]] = column[Option[Long]]("tax_id")
  val internationalCoffeeId: Column[String] = column[String]("international_coffee_id", O.DBType("VARCHAR"))
  val providerId: Column[String] = column[String]("provider_id", O.DBType("VARCHAR"))

  def * = (coffeeLoversId, taxId, internationalCoffeeId, providerId) <> (Coffee.tupled, Coffee.unapply)

  def ? = (coffeeLoversId, taxId, internationalCoffeeId.?, providerId.?).shaped.<>({r=>import r._; _1.map(_=> Coffee.tupled((_1, _2, _3.get, _4.get)))}, (_:Any) =>  throw new Exception("Inserting into ? projection not supported."))
}


object Coffees {
  def tableQuery(implicit schema: TableSchema) = TableQuery[Coffees]{ tag : Tag => new Coffees(tag, schema.name) }
}

我想运行的SQL查询是:

SELECT * from previous.coffees PRV 
LEFT JOIN current.coffees CUR 
ON PRV.international_coffee_id = CUR.international_coffee_id 
WHERE PRV.international_coffee_id IS NULL;

我能够达到:

for {
  (c,s) <- Coffees.tableQuery(previousSchema).leftJoin(
    Coffees.tableQuery(currentSchema)
    ) on((x,y) => x.internationalCoffeeId === y.internationalCoffeeId)
} yield(c)

这似乎给了我一个左外连接,但我无法过滤nulls服务器端(添加WHERE PRV.international_coffee_id IS NULL

我会感激任何指针或想法。

sql postgresql scala slick
1个回答
1
投票

我能够实现我的目标。首先,我尝试使用scala的条件理解:

for {
  (c,s) <- Coffees.tableQuery(previousSchema).leftJoin(
    Coffees.tableQuery(currentSchema)
    ) on((x,y) => x.internationalCoffeeId === y.internationalCoffeeId)
if(s.internationalCoffeeId.isEmpty)
} yield(c)

这工作,并在DB上测试我得到了预期的结果,我知道我在scala中过滤结果,而不是在DB服务器上。

所以我一直在努力,终于到了

for {
  (c,s) <- Coffees.tableQuery(previousSchema).leftJoin(
    Coffees.tableQuery(currentSchema)
    ) on(
    (x,y) => x.internationalCoffeeId === y.internationalCoffeeId
    ).filter(_._2.internationalCoffeeId.isEmpty)
} yield(c)

我还不清楚为什么编译器无法正确选择我的过滤器中匿名函数的输入参数类型的类型,但是我通过直接在元组上操作来处理它。我验证我在selectStatement上直接使用Query得到了所需的SQL查询(或者在这种情况下我的CompiledStreamingExecutable):

val query = Coffees.tableQuery(previousSchema).leftJoin(
    Coffees.tableQuery(currentSchema)
) on(
    (x,y) => x.internationalCoffeeId === y.internationalCoffeeId
).filter(_._2.internationalCoffeeId.isEmpty)
query.selectStatement
© www.soinside.com 2019 - 2024. All rights reserved.