从"组"中选择元素的首选方式是什么?小组的一部分? (groupBy导致[key - > group]关系)。如果可能的话,它应该导致一次db命中,或至少一次点击量。
举个例子,我们假设我们有一个Locations(id)和一个Companies(id,locationId,establishedDate)表。我们怎样才能找到每个地点最老的公司?
我会这样做的:
Locations.join(Companies).on(_.id === _.locationId).groupBy(_._1).flatMap {
case (location, companies) =>
companies.map(_._2).sortBy(_.foundedDate).take(1).map {
company => (location, company)
}
}
但这会产生运行时异常:
scala.slick.SlickException: Unsupported query shape containing .groupBy without subsequent .map
at scala.slick.compiler.FuseComprehensions.fuse(Relational.scala:200)
...
答案 0 :(得分:1)
我不熟悉Scala或Slick,但如果它在底层使用SQL,那么这不会起作用。在大多数实现中,查询返回的元素需要是类别值之一(在这种情况下是位置和公司)或聚合函数。
这可能有用......
SELECT location.id, company.id, MAX(foundedDate)
FROM companies INNER JOIN locations ON (locations.id = companies.locationId)
GROUP BY location.id, company.id
ORDER BY location.id, MAX(foundedDate)
......但这在功能上等同于通过以下方式进行排序:
SELECT location.id, company.id, foundedDate
FROM companies INNER JOIN locations ON (locations.id = companies.locationId)
ORDER BY location.id, foundedDate
要查找最老的公司而不需要过滤结果,我们可以使用相关的子查询:
SELECT location.id, company.id, foundedDate
FROM companies INNER JOIN locations ON (locations.id = companies.locationId)
WHERE foundedDate = (SELECT MAX(foundedDate from companies c2 where c2.locationId = location.id)
如果他们的创建日期相同,则可以按位置返回多家公司。
如何将其映射回Scala / Slick,我无法说,但希望它有所帮助。
答案 1 :(得分:0)
Slick不会为此类查询生成最佳代码,如果您在此处查询此查询也是如此。 MySQL可能很重(如果同一地点有几家公司在同一天成立,可能会很模糊)。因此,更简单的解决方案可能是单独选择公司,按位置对它们进行分组,并按数据库外的日期排序,然后将它们与位置进行匹配。
val locations = Locations.list.map(location => (l.id,location)).asMap
val lcPairs = Companies.list
.group(_.locationId)
.map{ case (locationId, companies) => (
locations(id),companies.sort(_.foundedDate).head
)}