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

SQL SUM/AVG query exclude rows in postgres

我有一个 table 存储问卷结果。 table 的列名为:

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,结果如下:
总和:

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

平均:

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

我怎样才能做到这一点?

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;

只需将 -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 开始会更简单。