分组与“拥有”'关于光滑+游戏的条款

时间:2018-04-05 10:02:12

标签: 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'有'他们给出的条款似乎更简单。

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:无法将节点转换为SQL理解

1 个答案:

答案 0 :(得分:1)

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