【问题标题】:PostgreSQL - Removing NULLS row and column from conditional aggregation resultsPostgreSQL - 从条件聚合结果中删除 NULLS 行和列
【发布时间】:2018-11-09 08:27:47
【问题描述】:

我有一个使用条件聚合的多维表查询

select A,
   SUM(case when D = 3 then D end) as SUM_D1,
   SUM(case when D = 4 then D end) as SUM_D2)

结果:

A    SUM_D1  SUM_D2
-------------------
a1   100     NULL
a1   200     NULL
a3   NULL    NULL
a4   NULL    NULL

但是,我想隐藏所有 NULL 行和列,如下所示:

A   SUM_D1 
-----------
a1   100 
a1   200 

我已经寻找过类似的问题,但它们不是我的预期答案。

非常感谢任何帮助,

谢谢

【问题讨论】:

  • 使用having 过滤IS NOT NULLwhere 以及派生表。对于不显示列,无法使用普通 SQL。
  • @dnoeth,你能告诉我更多细节吗?

标签: sql postgresql aggregate-functions


【解决方案1】:

我认为这是你想要的:

select A,
       coalesce(sum(case when D = 3 then D end),
                sum(case when D = 4 then D end)
               ) as sum_d
from t
group by A
having sum(case when d in (3, 4) then 1 else 0 end) > 0;

请注意,这仅返回一列 - 如您的示例所示。如果数据中同时包含“3”和“4”,则该值为“3”。

如果您想要一个返回可变列数的查询,那么您需要使用动态 SQL 或其他一些方法。 SQL 查询返回固定数量的列。

一种方法是将值作为数组返回:

select a,
       array_agg(d order by d) as ds,
       array_agg(sumd order by d) as sumds
from (select a, d, sum(d) as sumd
      from t
      where d in (3, 4)
      group by a, d
     ) d
group by a;

【讨论】:

  • 谢谢,我认为你的表达式中的有子句可能有助于我隐藏 NULL 行。但我认为隐藏一个空列是不可能的。
  • @DuyHuynh 。 . .除非您使用动态 SQL,否则您不能“​​隐藏”列。这些列在SELECT 中明确指定。
【解决方案2】:

要过滤全空行,您可以使用 HAVING

select *
from 
 (
    select A,
       SUM(case when D = 3 then D end) as SUM_D1,
       SUM(case when D = 4 then D end) as SUM_D2)
    ...
 ) as dt
where SUM_D1 is not null 
  and SUM_D2 is not null

当然,如果您有像示例中那样的简单条件,则最好在聚合之前过滤

select A,
   SUM(case when D = 3 then D end) as SUM_D1,
   SUM(case when D = 4 then D end) as SUM_D2)
...
where D in (3,4)

现在至少一个计算将返回一个值,因此无需检查全空。

要过滤全 NULL 列,您需要一些动态 SQL:

  • 使用插入/选择在临时选项卡中实现数据
  • 扫描每一列的全空select 1 from temp having count(SUM_D1) > 0
  • 基于此动态创建Select列表
  • 运行选择

但是你为什么认为你需要这个?如果用户运行相同的存储过程并为每次运行接收不同数量的列,这会让人感到困惑。

【讨论】:

    【解决方案3】:

    我可能误解了你的问题,因为解决方案看起来很简单:

    select A,
       SUM(case when D = 3 then D end) as SUM_D1,
       SUM(case when D = 4 then D end) as SUM_D2)
    where D is not null
    

    这不是你想要的,是吗? :-)

    【讨论】:

    • 在我的例子中,我认为 D 不是 null 总是正确的,因为 D = {3,4}。值为 null,因为 D=3 和 A =a3 为 null,依此类推。
    【解决方案4】:

    出现空值是因为case statement未处理的条件

    select A,
       SUM(case when D = 3 then D end) as SUM_D1,
       SUM(case when D = 4 then D end) as SUM_D2
     from
        Table1
     group by
         A
     having 
         (case when D = 3 or D = 4 then D end) is not null
    

    正如评论所说,如果你想抑制空值。你可以使用 is not null 来抑制空值

    【讨论】:

    • OP 不想显示零而不是 NULL,他想抑制那些行/列
    • 是的.. D 有这两个值,我想念 op 想要的.. Op 想要压制那些.. 不改变值..
    • having D is not null 不会运行,聚合后没有单独的D,必须在WHERE
    • 在你的表达中,如果D中存在3和4,那么have子句总是正确的,对吗?我认为我的情况下的空值来自值 D =3 和 A = a3 不存在
    • @DuyHuynh 你的 case when d= 3 or d=4 将显示 d ,如果没有,则值变为 null 因为如果 d != 3 or d != 4 不处理条件,我会过滤,当然 a3 不会存在是因为他没有满足条件..
    猜你喜欢
    • 1970-01-01
    • 2020-07-02
    • 1970-01-01
    • 1970-01-01
    • 2015-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多