【问题标题】:Query average point each student查询每个学生的平均分
【发布时间】:2017-06-02 08:06:28
【问题描述】:

我有 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;

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

【问题讨论】:

    标签: sql json postgresql


    【解决方案1】:

    这包括没有分数的学生:

    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)
    

    【讨论】:

    • 谢谢提醒 avg - 我将总和除以计数 :)
    【解决方案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 所说 - 我们可能应该计算没有考试的学期仍然作为学期......

    【讨论】:

    • 这仅在marks 不能是NULL{}(空对象)时才有效。
    • 那在 OP 上,但他/她没有具体说明。但是延期学期是学期,无论如何它都不会伤害avg()(至少它值得一提,恕我直言)
    【解决方案3】:

    感谢大家提出使用 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;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-16
      • 2012-02-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-02
      • 1970-01-01
      相关资源
      最近更新 更多