【问题标题】:Group by in many-to-many join with Quill与 Quill 以多对多方式进行分组
【发布时间】:2017-12-18 08:51:04
【问题描述】:

我正在尝试使用 Quill 实现以下 PostgreSQL 查询的功能:

select books.*, array_agg(authors.name) from books 
join authors_books on(books.id = authors_books.book_id)
join authors on(authors.id = authors_books.author_id)
group by books.id

现在我的 Quill 版本中有这个:

val books = quote(querySchema[Book]("books"))
val authorsBooks = quote(querySchema[AuthorBook]("authors_books"))
val authors = quote(querySchema[Author]("authors"))

val q: db.Quoted[db.Query[(db.Query[Book], Seq[String])]] = quote{
        books
            .join(authorsBooks).on(_.id == _.book_id)
            .join(authors).on(_._2.author_id == _.id)
            .groupBy(_._1._1.id)
            .map {
                case (bId, q) => {
                    (q.map(_._1._1), unquote(q.map(_._2.name).arrayAgg))
                }
            }
    }

如何摆脱结果中的嵌套查询 (db.Query[Book]) 并获得一本书?

【问题讨论】:

  • 您是否尝试过使用 flatMap 而不是地图?我不确定,只是猜测
  • 我想是这样,但我不记得结果是什么,我与这个查询斗争了很长时间,今天晚些时候我会再回来告诉你。跨度>

标签: postgresql scala quill.io


【解决方案1】:

我可能对 SQL 有点生疏,但您确定您的查询有效吗?特别是我发现您在 group by books.id 时使用 select books.* 表示怀疑,即您直接返回未分组的字段。尝试直接翻译错误的查询是导致事情出错的原因

解决此问题的一种方法是对所有字段执行group by。假设Book 被声明为:

case class Book(id: Int, name: String)

你可以的

  val qq: db.Quoted[db.Query[((Index, String), Seq[String])]] = quote {
    books
      .join(authorsBooks).on(_.id == _.book_id)
      .join(authors).on(_._2.author_id == _.id)
      .groupBy(r => (r._1._1.id, r._1._1.name))
      .map {
        case (bId, q) => {
          // (Book.tupled(bId), unquote(q.map(_._2.name).arrayAgg)) // doesn't work
          (bId, unquote(q.map(_._2.name).arrayAgg))
        }
      }
  }

  val res = db.run(qq).map(r => (Book.tupled(r._1), r._2))

不幸的是,您似乎无法在quote 中应用Book.tupled,因为您收到错误

单子组合不能使用应用连接来表达

但您可以在 db.run 调用后轻松完成此操作以取回您的 Book

另一种选择是仅按Book.id 进行分组,然后再次加入Book 表以取回所有字段。如果Book中有很多字段,这实际上可能更干净、更快

【讨论】:

  • 是的,这是一个有效的 PostgreSQL 查询,但我不确定它是否正确地转换为 Quill 的 AST。 Book 表中有 20 个字段。我会尝试再次加入 Book 并通知您。
  • @DanielAlexandrov,好的,我错了,这可能是一个有效的 SQL 查询如果数据库支持可选功能 T301 “功能依赖”,但看起来 Quill 没有提供在其 DSL 中表达此类功能的方法,因此您仍然必须使用一种非可选方式:按所有字段分组或附加连接。
  • 您对 Book 中多个字段进行分组的建议非常有用,显然可以在 GROUP BY 中添加表名本身。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-17
  • 2014-05-29
  • 2022-12-03
  • 2016-07-12
  • 2017-02-03
  • 2016-07-24
  • 1970-01-01
相关资源
最近更新 更多