简体   繁体   English

Scala Slick:如何进行除联接(左外部联接为null)?

[英]Scala Slick: How to do an except join (left outer join with is null)?

I'm using scala 2.11, slick 2.1.0 and postgres 9.6. 我正在使用scala 2.11,slick 2.1.0和postgres 9.6。 Major version upgrade is out of the question. 大版本升级是不可能的。

I have 2 identical tables (created from the same model) and I want to do an except join (left outer join with is null): 我有2个相同的表(从相同的模型创建),我想做一个例外联接(左边的外部联接为null): 除了加入

My model looks like this: 我的模型如下所示:

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) }
}

The SQL query I would like to run is: 我想运行的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;

I was able to get as far as: 我能够做到:

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

that seems to give me a left outer join, but I'm having trouble filtering for nulls server side (adding the WHERE PRV.international_coffee_id IS NULL ) 这似乎给了我一个左外部WHERE PRV.international_coffee_id IS NULL ,但是我在过滤null服务器端时遇到了麻烦(添加WHERE PRV.international_coffee_id IS NULL

I'll be grateful for any pointers or ideas. 如果有任何建议或想法,我将不胜感激。

I was able to achieve my goal. 我能够实现自己的目标。 First I tried using scala's conditional for-comprehension: 首先,我尝试使用scala的条件理解:

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

This worked, and testing on the DB I got the expected result, by I knew I was filtering the result in scala, rather than on the DB server. 这可以正常工作,并且在数据库上进行测试得到了预期的结果,因为我知道我是在scala中而不是在数据库服务器上过滤结果。

So I kept trying and finally got to 所以我一直努力,终于

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

I'm not clear yet on why the compiler couldn't pick up the type correctly the type of the input parameter for the anonymous function in my filter, but I dealt with it by operating directly on the tuple. 我还不清楚为什么编译器无法正确选择类型,而我的过滤器中却没有为匿名函数输入参数的类型,但是我直接在元组上进行处理。 I verified that I'm getting the desired SQL query using selectStatement directly on my Query (or in this case my CompiledStreamingExecutable ): 我验证selectStatement可以在Query (或本例中为CompiledStreamingExecutable )中直接使用selectStatement获得所需的SQL查询:

val query = Coffees.tableQuery(previousSchema).leftJoin(
    Coffees.tableQuery(currentSchema)
) on(
    (x,y) => x.internationalCoffeeId === y.internationalCoffeeId
).filter(_._2.internationalCoffeeId.isEmpty)
query.selectStatement

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM