Как выразить этот запрос в пятно с участием группы, имея, считать - PullRequest
0 голосов
/ 18 октября 2018

Предположим, у меня есть таблица, определенная следующим образом в Slick 3.2.3:

class ATable(tag: Tag) extends Table[(Int, Option[Boolean])](tag, "a_table") {
  def someInt = column[Int]("some_int")
  def someBool = column[Option[Boolean]]("some_bool")
  def * = (someInt, someBool)
}
object ATable extends TableQuery(new ATable(_))

и немного данных для этого:

insert into a_table
values
(1, true),
(2, null),
(2, true),
(2, null),
(3, true),
(3, true),
(3, null);

Теперь я хотел бынайти эти целые в таблице, где есть ровно одна строка, где some_bool не равно null.Это не сложно в SQL:

select some_int
from a_table
group by some_int
having count(some_bool) = 1;

Это прекрасно работает.Итак, давайте попробуем это с Slick:

ATable
 .groupBy(_.someInt)
 .filter(_._2.map(_.someBool).countDefined === 1)
 .map(_._1)

И пока он скомпилируется, во время выполнения произойдет сбой с сообщением об ошибке «slick.SlickTreeException: Cannot convert node to SQL Comprehension».Это известное ограничение или ошибка в пятне?Или я должен написать свой запрос по-другому?Конечно, можно написать это с помощью подзапроса, но я бы лучше понял, почему вещь groupBy не работает ...

1 Ответ

0 голосов
/ 18 октября 2018

Эквивалентность Slick вашего SQL должна выглядеть примерно так: query в следующем примере:

val aTable: TableQuery[ATable] = TableQuery[ATable]

val setupAction: DBIO[Unit] = DBIO.seq(
  aTable.schema.create,
  aTable += (1, Some(true)),
  aTable += (2, None),
  aTable += (2, Some(true)),
  aTable += (2, None),
  aTable += (3, Some(true)),
  aTable += (3, Some(true)),
  aTable += (3, None)
)

val setupFuture: Future[Unit] = db.run(setupAction)

val f = setupFuture.flatMap{ _ =>
  val query =
    aTable.groupBy(_.someInt).
      map{ case (someInt, group) => (someInt, group.map(_.someBool).countDefined) }.
      filter(_._2 === 1).
      map(_._1)

  println("Generated SQL for query:\n" + query.result.statements)
  db.run(query.result.map(println))
}

// Generated SQL for query:
// List(select "some_int" from "a_table" group by "some_int" having count("some_bool") = 1)
// Vector(1, 2)
...