web-dev-qa-db-ja.com

SELECT DISTINCT in Scala slick

Slick 1を使用していますが、クエリにフィルターを適用して、関連するテーブルの条件に一致するすべてのエンティティを検索できるようにする必要があります。

Slickドキュメントを使用したこの例は、私がやろうとしていることを示しています(これは、私の状況に近い不自然な例です)。

ここでは、西海岸のサプライヤーから提供されるすべてのコーヒーが欲しいです。コーヒーだけが欲しいのですが、フィルターを適用するためにサプライヤーにナビゲートすることにのみ興味があります。

val westCoast = Seq("CA", "OR", "WA")
val implicitInnerJoin = for {
  c <- Coffees
  s <- Suppliers if c.supID === s.id && s.state inSet westCoast
} yield c

これは問題なく機能しますが、Suppliersテーブルに複数の一致がある場合はCoffeesが複製されます。

明らかな回避策は、通常のSQLでSELECTDISTINCTを実行することです。しかし、私はそれをここで行う方法を見つけることができません。

理論的には、次のことができます。

query.list.distinct

結果がすでに返された後。ただし、PAGINGサポートも実装しているので、データベースから既に戻ってきたら結果を処理したくないでしょう。ページングのサポートは次のとおりです。

query.drop(offset).take(limit).list

つまり、一言で言えば、I need出て行くクエリでSELECTDISTINCTを指定する方法です。

誰かアイデアはありますか?

31
noplay

回避策として、groupByの使用を試みることができます。

query.groupBy(x=>x).map(_._1)

個別と同じセマンティクスを持つ必要がありますが、パフォーマンスについてはわかりません。

21
Martin Kolinek

Slick 3.1.0では、distinctおよびdistinctOn関数を使用できます( Slick 3.1.0リリースノート )。例えば:

val westCoast = Seq("CA", "OR", "WA")
val implicitInnerJoin = for {
  c <- Coffees
  s <- Suppliers if c.supID === s.id && s.state inSet westCoast
} yield c

db.run(implicitInnerJoin.distinctOn(_.name).result)
16
Valerii Rusakov

これはまだ実装されていないと思います。 https://github.com/slick/slick/issues/96 を参照してください

5
Eugene Ryzhikov

複数の列に別個のcoffee.nameおよびcoffee.priceの場合:

val westCoast = Seq("CA", "OR", "WA")
val implicitInnerJoin = for {
  c <- Coffees
  s <- Suppliers if c.supID === s.id && s.state inSet westCoast
} yield c

db.run(implicitInnerJoin.map(f => (f.name, f.price, f.state)).distinctOn(p => (p._1, p._2)).result)
2
binshi