scala – 如何在Slick中进行聚合查询?
发布时间:2020-12-16 08:53:08 所属栏目:安全 来源:网络整理
导读:例如,我有以下表定义: 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 size = colu
例如,我有以下表定义:
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 size = column[Int]("size") def * = id ~ houseId ~ size } 我想为每个房子选择最大的房间. 我想出了以下技巧: val query = { (r1,r2) <- Rooms leftJoin Rooms on ((r1,r2) => r1.houseId === r2.houseId && r1.size > r2.size ) if r2.id.isNull } yield r1 它做我需要的,但是很难看,完全不可读,而且似乎伤害了性能.我试图在查询中使用groupBy,但似乎我误解了一些核心概念 – 我无法使这些类型正确. 有没有更好的方法在Slick中进行这样的聚合查询? 解决方法
首先,这种查询在纯SQL中并不完全简单. Slick groupBy最终会转换为SQL GROUP BY,因此要使用它,我们需要一个带有GROUP BY的SQL查询
一个这样的查询可能看起来像 SELECT r2.* FROM (SELECT r.houseId,MAX(size) as size FROM Rooms r GROUP BY r.houseId) mx INNER JOIN Rooms r2 on r2.size = mx.size and r2.houseId = mx.houseId 现在可以将其翻译为光滑的 val innerQuery = Query(Rooms).groupBy(_.houseId).map { case (houseId,rows) => (houseId,rows.map(_.size).max) } val query = for { (hid,max) <- innerQuery r <- Rooms if r.houseId === hid && r.size === max } yield r 但是,我在当前版本的光滑版中的其他查询中使用的聚合查询存在问题. 但是可以使用EXISTS在没有GROUP BY的情况下编写查询 SELECT r.* FROM Rooms r WHERE NOT EXISTS ( SELECT r2.id FROM Rooms r2 WHERE r2.size > r.size and r2.houseId = r.houseId) 这可以再次转化为浮油 val query = for { r <- Rooms if !Query(Rooms).filter(_.houseId === r.houseId).filter(_.size > r.size).exists } yield r 另一个选择可能是使用window functions,但我无法真正帮助你,我不认为光滑可以与他们合作. (请注意,我手边没有scala编译器,因此代码中可能存在错误) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |