当我尝试对查询执行Query(query.length).first
时,表示两个表的连接,这些表有几个具有相同名称的列,我得到格式错误的sql。考虑一下这个例子:
// in Main.scala
import scala.slick.driver.MySQLDriver.simple._
object Main extends App {
object Houses extends Table[Long]("Houses") {
def id = column[Long]("id")
def * = id
}
object Rooms extends Table[(Long, Long)]("Rooms") {
def id = column[Long]("id")
def houseId = column[Long]("houseId")
def * = id ~ houseId
}
val query = for {
h <- Houses
r <- Rooms
if h.id === r.houseId
} yield (h, r)
println("QUERY: " + Query(query.length).selectStatement)
}
// in build.sbt
scalaVersion := "2.10.2"
libraryDependencies += "com.typesafe.slick" %% "slick" % "1.0.1"
此示例生成以下SQL:
select x2.x3 from
(select count(1) as x3 from
(select x4.`id`, x5.`id`, x5.`houseId`
from `Houses` x4, `Rooms` x5 where x4.`id` = x5.`houseId`) x6) x2
这显然是错误的并且被MySQL拒绝,因为id
列中的select x4.id, x5.id
列重复。
我可以尝试执行以下操作:
query.list.size
但是这将从查询中提取所有行并通过网络发送它们,这将极大地阻碍性能。
我做错了什么?有没有办法解决它?
答案 0 :(得分:6)
这是一个有趣的问题。通常使用SQL,您将别名列为可能导致名称冲突的另一列,但我不确定如何使用Slick(或者甚至可能)。但是你可以解决这个问题,我相信如果你只想选择一个列,那就算了:
val query = for {
h <- Houses
r <- Rooms
if h.id === r.houseId
} yield h.id.count
现在不推荐对count
id
调用,但是这个调用生成了一个干净的sql语句,如下所示:
select count(x2.`id`) from `Houses` x2, `Rooms` x3 where x2.`id` = x3.`houseId`
我尝试使用.length
的任何内容都会产生一堆不正确的SQL。
修改强>
在回复您的评论时,您希望保留查询的方式(让我们忘记查询本身因连接中的字段冲突/歧义而中断),然后还能够导出计数查询从它看起来像这样:
def main(args: Array[String]) {
val query = for {
h <- Houses
r <- Rooms
if h.id === r.houseId
} yield (h,r)
val lengthQuery = query.map(_._1.id.count)
}
这里的要点是,你应该能够通过选择一个列(而不是完整的对象)然后获取map
来获取任何查询并count
到计数查询柱。在这种情况下,因为结果是Tuple2
,我必须进入额外的级别才能进入id
列,但我认为您可以了解相关信息。