【问题标题】:Skip whole row if aggregated value is null如果聚合值为空,则跳过整行
【发布时间】:2018-12-07 19:46:09
【问题描述】:

这是我的方法:

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

查询返回如下输出:

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

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

【问题讨论】:

  • 只要使用having -- having sum(case when department_id=6 then total end) is not null...

标签: sql postgresql aggregate having-clause


【解决方案1】:

添加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) 混淆。第一个带有误导性的括号,这些括号被去掉了。第二个含义不同。见:

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

【讨论】:

  • @MuhammedIqbal 。 . .这绝对是比任何以select distinct 开头的查询更好的解决方案。
【解决方案2】:

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

【讨论】:

  • 实际上,要在 where 条件中引用 a6,您必须将当前选择包装在另一个选择语句中。
  • @sgeddes 请给我一个创建子查询的例子。我是这类复杂查询的新手。
  • @MuhammadIqbal -- 我个人会使用having,但如果你想使用子查询,它看起来像这样:select * from (your query here without the order by) t where a6 is not null order by no...
  • 对,我现在明白了,我们可以在 where 子句中使用子查询。谢谢@sgeddes
【解决方案3】:

在分组后添加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

【讨论】:

  • 导致“a6”列不存在的错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-12-12
  • 2015-10-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-20
相关资源
最近更新 更多