SQL SUM / AVG查询排除postgres中的行

时间:2015-02-16 20:24:31

标签: sql postgresql sum aggregate average

我有一个存储问卷结果的表格。该表包含名为:

的列
q1,q2,q3,q4 ....

有效值为正0到100.如果没有回答问题,则值为-1,因此我以行结束:

       q1   q2   q3   q4  ...  
row 1  10  100   -1   50  
row 2  20   -1   20   20  
row 3  50   60  100   -1  

我想将q1汇总到q4,结果如下:
SUM:

q1 => 80  
q2 => 160  
q3 => 120  
q4 => 70  

AVG:

q1 => 80 / 3  
q2 => 160 / 2  
q3 => 120 / 2  
q4 => 70 / 2

我怎样才能做到这一点?

2 个答案:

答案 0 :(得分:4)

只需将-1替换为 NULL ,然后直接使用列上的聚合函数:

SELECT sum(q1) AS q1_sum
     , sum(q2) AS q2_sum
     , sum(q3) AS q3_sum
     , sum(q4) AS q4_sum
     , count(q1) AS q1_ct
     , count(q2) AS q2_ct
     , count(q3) AS q3_ct
     , count(q4) AS q4_ct
     , round(avg(q1),2) AS q1_avg
     , round(avg(q2),2) AS q2_avg
     , round(avg(q3),2) AS q3_avg
     , round(avg(q4),2) AS q4_avg
FROM (
  SELECT NULLIF(q1, -1) AS q1
       , NULLIF(q2, -1) AS q2
       , NULLIF(q3, -1) AS q3
       , NULLIF(q4, -1) AS q4
  FROM   tbl
  ) t;

SQL Fiddle.

<强>为什么吗
所有这些聚合函数都会自动排除NULL值 将不存在的值存储为NULL将更容易开始。

答案 1 :(得分:0)

SQL没有针对每个列的平均值进行优化,就像这样。对行分组更好。但是,您可以通过为每列手动编写这样的条件数据透视语句来解决此问题:

    SELECT 
    SUM(CASE WHEN q1 > 0 THEN q1 ELSE 0 END)/
      SUM(CASE WHEN q1 > 0 THEN 1 ELSE 0 END) AS q1_avg,
    SUM(CASE WHEN q2 > 0 THEN q1 ELSE 0 END)/
      SUM(CASE WHEN q2 > 0 THEN 1 ELSE 0 END) AS q2_avg
    FROM table;