1

groupBy の「グループ」部分から要素を選択する好ましい方法は何ですか? (groupBy は [キー -> グループ] 関係になります)。可能であれば、1 つのデータベース ヒット、または少なくとも一定量のヒットが発生するはずです。

例として、Locations(id) テーブルと Companies(id, locationId,foundDate) テーブルがあるとします。各場所で最も古い会社を見つけるにはどうすればよいでしょうか?

私はこのようにしたでしょう:

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)
...
4

2 に答える 2

1

私は Scala や Slick には詳しくありませんが、内部で SQL を使用している場合、これは機能しません。ほとんどの実装では、クエリによって返される要素は、カテゴリ値 (この場合は場所と会社) の 1 つまたは集計関数である必要があります。

これはうまくいくかもしれません...

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 にマップされるかはわかりませんが、少しは役に立てば幸いです。

于 2014-07-12T13:08:46.613 に答える
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
                   )}
于 2014-07-12T13:03:25.740 に答える