我在浮油中获得一些好的查询时遇到了一些麻烦。 假设我们有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";
我真的很感激。