2017-06-02 102 views
3

我有2个表:查询平均点每个学生

学生:

id  name  
    2  ABC  
    13  DEF  
    22  GHI  

学期:

id  student_id  sem  marks          
    1  2    1  {"math":3, "physic":4, "chemis":5} 
    2  2    2  {"math":2.5, "physic":4.5, "chemis":5} 
    3  2    3  {"math":3, "physic":3.5, "chemis":4} 
    5  13    1  {"math":3, "physic":4, "chemis":5} 
    6  13    2  {"math":3, "physic":4, "chemis":5} 

因此,例如用student_id数据= 2:

平均分数=( (3 + 4 + 5)/ 3)+(2.5 + 4.5 + 5)/ 3 +(3 + 3.5 + 4)/ 3)/3=3.83

有没有办法按学生ID查询平均分数组?

student_id  average  number_of_sems  
    2    3.83  3     
    13    xxx   2   

我试图通过主题来算:

SELECT 
    t1.student_id, 
    t1.count, 
    (SELECT sum(xx.count) 
    FROM 
    (SELECT (marks:: JSON ->> 'math') :: DOUBLE PRECISION AS count 
     FROM "Semester" 
     WHERE student_id= t1.student_id) AS xx) 
FROM 
    (
    SELECT 
     student_id, 
     count(1) 
    FROM "Semester" 
    GROUP BY student_id 
) AS t1; 

但仍然不知道如何继续。这可能是不好的解决方案。

回答

2

这包括学生没有标记:

SELECT st.id, avg(m.value) 
FROM student st 
    LEFT JOIN semester se 
     ON st.id = se.student_id 
    LEFT JOIN LATERAL (SELECT value::numeric 
         FROM jsonb_each_text(se.marks) 
        ) m 
     ON TRUE 
GROUP BY st.id; 

┌────┬────────────────────┐ 
│ id │  avg   │ 
├────┼────────────────────┤ 
│ 2 │ 3.8333333333333333 │ 
│ 13 │ 4.0000000000000000 │ 
│ 22 │     │ 
└────┴────────────────────┘ 
(3 rows) 
+0

谢谢你提醒平均 - 我分数和:) –

2

试试这个:

select student_id 
, avg((marks->>m)::float) average 
, count(distinct sem) number_of_sems 
from semestr s 
join student t on s.student_id = t.id 
left outer join json_object_keys(marks) m on true 
group by student_id; 
student_id |  average  | number_of_sems 
------------+------------------+---------------- 
      2 | 3.83333333333333 |    3 
     13 |    4 |    2 
(3 rows) 

更新

为pozs说 - 我们也许应该没有考试还算学期为semestres ...

+0

这只会工作,当'marks'不能'NULL'和'{}'(空对象)没有。 – pozs

+0

是真的。你认为我应该在没有任何考试的情况下算一个学期吗? –

+0

这是在OP上,但他/她没有指定。但延期学期是学期&它不会伤害'平均()'无论如何(至少它值得注意恕我直言) – pozs

0

感谢所有使用json_each_text()和avg()函数的想法。 所以在情况下,如果目的是在1名学生每个科目获得平均分:

SELECT 
    st.id, 
    json_data.key AS subject, 
    SUM(json_data.value::DOUBLE PRECISION) AS sum_value, 
    avg(json_data.value::DOUBLE PRECISION) AS avg_value 
FROM student AS st, 
json_each_text(st.marks::JSON) AS json_data 
GROUP BY si.id, subject;