如果聚合值为空,则跳过整行

Skip whole row if aggregated value is null

这是我的方法:

select distinct (invoice_no) as no,sum(total),
                sum(case when department_id=2 then total end) as a2,
                sum(case when department_id=3 then total end) as a3,
                sum(case when department_id=4 then total end) as a4,
                sum(case when department_id=5 then total end) as a5,
                sum(case when department_id=6 then total end) as a6
from article_sale
where  invoice_date = '2018-10-01' group by no order by no ASC

查询returns输出如下:

no      sum a2      a3    a4    a5      a6
68630   690 NULL    75    404   NULL    210.8
68631   0   NULL    NULL  NULL  NULL    NULL
68632   132 NULL    45    87    NULL    NULL
68633   75  NULL    75    NULL  NULL    NULL
68634   523 NULL    130   NULL  NULL    392.55
68635   0   NULL    NULL  NULL  NULL    NULL
68636   310 NULL    NULL  218   NULL    91.91
68637   273 NULL    NULL  NULL  NULL    273.24
68638   0   NULL    NULL  NULL  NULL    NULL

我只想获取 a6NOT NULL 的行。应过滤其他行。
期望的输出:

no      sum a2      a3    a4    a5      a6
68630   690 NULL    75    404   NULL    210.8
68634   523 NULL    130   NULL  NULL    392.55
68636   310 NULL    NULL  218   NULL    91.91
68637   273 NULL    NULL  NULL  NULL    273.24

如何最好地实现这一目标?

如果你想过滤空值,你可以在 WHERE 条件中加入 AND a6 IS NOT NULL

分组依据后加HAVING a6 IS NOT NULL。所以查询会变成

select distinct (invoice_no) as no,sum(total), 
sum(case when department_id=2 then total end) as a2, 
sum(case when department_id=3 then total end) as a3, sum(case when department_id=4 then total end) as a4, 
sum(case when department_id=5 then total end) as a5, 
sum(case when department_id=6 then total end) as a6 from article_sale where invoice_date = '2018-10-01' 
group by no having sum(case when department_id=6 then total end) is not null order by no ASC

添加一个HAVING子句:

SELECT invoice_no                                  AS no
     , sum(total)                                  AS sum_total
     , sum(total) FILTER (WHERE department_id = 2) AS a2
     , sum(total) FILTER (WHERE department_id = 3) AS a3
     , sum(total) FILTER (WHERE department_id = 4) AS a4
     , sum(total) FILTER (WHERE department_id = 5) AS a5
     , sum(total) FILTER (WHERE department_id = 6) AS a6
FROM   article_sale
WHERE  invoice_date = '2018-10-01'
GROUP  BY 1
HAVING sum(total) FILTER (WHERE department_id = 6) IS NOT NULL
ORDER  BY 1;

但首先要放弃多余的、昂贵的 DISTINCT。在应用 GROUP BY 之后,行必然是不同的。也不要混淆 DISTINCT (invoice_no)DISTINCT ON (invoice_no)。第一个有误导性的括号被去掉了。第二个有不同的含义。参见:

  • Select first row in each GROUP BY group?

还为您的条件聚合使用现代的、更快的 FILTER 子句。参见:

  • How can I simplify this game statistics query?