使用多个连接时,在Slick 3.1.1上获取行数

时间:2017-10-10 19:08:02

标签: mysql scala slick

我在浮油中获得一些好的查询时遇到了一些麻烦。 假设我们有3个表,声明为:

import slick.driver.MySQLDriver.api._

case class Foo(id: Int, bar: Option[Int])
case class Bar(id: Int, name: String)
case class Baz(id: Int, fooId: Int, prop: String)

class Foos(tag: Tag) extends Table[Foo](tag, "foo") {
  def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
  def bar = column[Option[Int]]("bar")
  def * = (id, bar) <> (Foo.tupled, Foo.unapply)
}

class Bars(tag: Tag) extends Table[Bar](tag, "bar") {
  def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
  def name = column[String]("name")
  def * = (id, name) <> (Bar.tupled, Bar.unapply)
}

class Bazs(tag: Tag) extends Table[Baz](tag, "baz") {
  def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
  def fooId = column[Int]("foo_id")
  def prop = column[String]("prop")
  def * = (id, fooId, prop) <> (Baz.tupled, Baz.unapply)
}

许多Foo属于Bar,而一个Baz属于一个Foo。我想加入所有三个表,过滤掉它们,并获得总行数。 所以我这样做了:

val foos = TableQuery[Foos]
val bars = TableQuery[Bars]
val bazs = TableQuery[Bazs]

val q = for {
  ((f, b), bz) <- foos joinLeft bars on (_.bar === _.id) joinLeft bazs on (_._1.id === _.fooId)
} yield (f, b, bz)

val qx = q
  .filter(_._2.map(_.name) === "Hello")
  .filter(_._3.map(_.prop) === "bye")

println(qx.length.result.statements.mkString)

结果如下:

SELECT count(1)
FROM (SELECT
        x2.`id`      AS x3,
        x2.`bar`     AS x4,
        (CASE WHEN (x5.`name` IS NULL)
          THEN NULL
         ELSE 1 END) AS x6,
        x5.`id`      AS x7,
        x5.`name`    AS x8
      FROM `foo` x2 LEFT OUTER JOIN `bar` x5
          ON x2.`bar` = x5.`id`) x9 LEFT OUTER JOIN `baz` x10
    ON x9.x3 = x10.`foo_id`
WHERE ((CASE WHEN (x9.x6 IS NOT NULL)
  THEN x9.x8
        ELSE NULL END) = 'Hello') AND (x10.`prop` = 'bye')

正如您所看到的,该子查询对于性能而言非常糟糕。如果有人知道如何达到这个目的:

SELECT count(*)
FROM
  foo f
  LEFT JOIN bar b ON f.bar = b.id
  LEFT JOIN baz bz ON f.id = bz.foo_id
WHERE
  b.name = "Hello" AND bz.prop = "bye";

我真的很感激。

0 个答案:

没有答案