想象一下,我有一个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理解
答案 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)))