sql - slick+play 上带有 'HAVING' 子句的 Group By

标签 sql scala playframework slick

假设我有一个 SQL 表 grades,其中包含学生姓名和成绩结果等字段:

| student  |   grade   |
|----------|:---------:|
| Harry    |    Good   |
| Ron      |    Good   |
| Harry    |  Average  |
| Harry    |    Fail   |
| Hermione | Excellent |
| Hermione | Excellent |
| Ron      |  Average  |
| .....    |    ....   |

如果我想选择所有至少有两个“优秀”和零个“不及格”成绩的学生,可以这样做:

select student
from grades
group by student
having 
      sum(case when grade = 'Excellent' then 1 else 0 end) >= 2 and
      sum(case when grade = 'Fail' then 1 else 0 end)

如何将这样的查询转换为 Slick? 关于documentation他们给出的“Having”子句似乎更简单。

gradesTables
.groupBy(._student)
.map{ case(student, group) => (student, ???)}
.filter(???)
.list

在相关说明中,为什么我会收到以下错误:

   gradesTables
    .groupBy(._student)
    .map{ case(student, group) => (student, group.filter(_.grade == "Fail").length)}
    .list

错误是:

slick.SlickTreeException: Cannot convert node to SQL Comprehension

最佳答案

Slick 中的以下代码将生成您需要的 SQL:

val query: Query[(Rep[String], Rep[Option[Int]], Rep[Option[Int]]), (String, Option[Int], Option[Int]), Seq] =
  grades.groupBy( _.student ).map{ case (student, group) => 
    val groupList = group.map(_.grade)

    val gradeExcel = groupList.map( grade =>
      Case.If(grade === "Excellent").Then(1).Else(0) ).sum
    val gradeFail = groupList.map( grade =>
      Case.If(grade === "Fail").Then(1).Else(0) ).sum

    (student, gradeExcel, gradeFail)
  }.
  filter( g => g._2 >= 2 && g._3 === 0 )

// ...

println("Generated SQL:\n" + query.result.statements)
// Generated SQL:
// List(
//   select "STUDENT", sum((case when ("GRADE" = 'Excellent') then 1 else 0 end)), 
//   sum((case when ("GRADE" = 'Fail') then 1 else 0 end)) from "GRADES" group by "STUDENT" 
//   having (sum((case when ("GRADE" = 'Excellent') then 1 else 0 end)) >= 2) and 
//   (sum((case when ("GRADE" = 'Fail') then 1 else 0 end)) = 0)
// )

db.run(query.result.map(println))
// Vector((Hermione,Some(2),Some(0)))

关于sql - slick+play 上带有 'HAVING' 子句的 Group By,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49669533/

相关文章:

java - playframework:Job中的Request.current

java - 无法向 build.sbt 添加任何依赖项

grails - Grails 或 Play 框架的动态 ACL?

mysql - 选择要更新的查询

php - 获取sql中多列的合计

mysql - 过滤mysql中的别名

scala - 如何从Spark中的堆中删除/处理广播变量?

java - 如何在 Java 中进行没有副作用的编程?

sql - 获取 LEFT OUTER JOIN 的第一行

scala - 在代码中设置 akka TestKit 默认超时