我正在尝试在oracle中编写一个SQL脚本,该脚本按不同列对数据进行分组。
让我们看下面的示例:
class_name year student_id grade exam-id --------- ---- --------- ----- ------- A 2012 3 90 1 A 2012 4 80 1 A 2012 5 70 1 A 2013 3 90 1 A 2013 4 100 2 A 2013 5 70 1 A 2014 3 90 1 A 2014 4 100 2 A 2014 5 75 3 A 2015 3 85 4 A 2015 4 95 4 A 2015 5 80 4 A 2016 3 85 4 A 2016 4 90 5 A 2016 5 90 5
上表显示名为“ A”的班级,该班级每年有3名学生以及特定考试的成绩。每年都有一次新考试,如果学生决定参加考试,则表中将填入新的考试ID,否则(即学生未参加考试)表将再次被旧考试填入-id(和旧等级)
现在,我想显示每年实际参加考试的学生人数。
所以结果应该像这样:
class_name year num_of_students_took_the_exam --------- ---- ----------------------------- A 2012 3 A 2013 1 A 2014 1 A 2015 3 A 2016 2
我知道如何使用select和group-by以及select和group-by结果。但这似乎太复杂了。
select class_name, year, count(year) from (select class_name, min(year) as year, student_id, grade, min(exam-id) from my_table Where class_name = 'A' group by class_name, student_id, grade) group by class_name, year
是否有任何简单的sql脚本返回相同的结果?
谢谢
答案 0 :(得分:3)
可以稍微简化当前查询,但不能删除嵌套的聚合:
select class_name, year, count(*)
from
(select
class_name, min(year) as year, student_id, exam_id
from
my_table
Where
class_name = 'A'
group by
class_name, student_id, exam_id) -- don't group by grade, there might be two different exams with the same grade
group by
class_name, year
用LAG(或ROW_NUMBER)重写可能不是更简单/更有效
答案 1 :(得分:0)
你能做...
select distinct class_name, year, count (distinct class_name+'-'+min(year)+'-'+student_id+'-'+exam_id) as cnt
from my_table
where class_name = 'A'
答案 2 :(得分:0)
您可以将row_number()
函数与class_name, year, student_id, exam_id
的分组一起使用(主要逻辑取决于student_id
,exam_id
的分组),如以下:
select class_name, year,
count(rn) as num_of_students_took_the_exam
from
(
select class_name, year,exam_id,student_id,
row_number() over (partition by student_id, exam_id order by year ) as rn
from Exams
group by class_name, year, student_id, exam_id
order by class_name, year, student_id, exam_id
)
where rn = 1
group by class_name, year;
答案 3 :(得分:0)
您应该列出哪些年份参加了哪些考试。就您而言,您使用的是序列号。如果这是您的数据的真正结构,那么您可以:
select year, count(*)
from example e
where year - exam_id = 2012
group by year;
在实践中,这样的查询不会使用魔术数学。而是这样的:
select e.year, count(*)
from example e join
exams ee
on e.exam_id = ee.exam_id
where e.year = ee.year
group by e.year;