【问题标题】:How to ignore nulls in aggregate functions (AVG) when using multiple case statements使用多个 case 语句时如何忽略聚合函数 (AVG) 中的空值
【发布时间】:2019-02-13 16:40:29
【问题描述】:

我正在使用 SQL Server 查找某些列的平均值,但我想忽略任何值为 0 或 null 的列

我正在阅读的表格:

我的查询:

SELECT AVG(CASE WHEN [January-Margin] > 0 THEN [January-Margin] ELSE NULL END + CASE WHEN [February-Margin] > 0 THEN [February-Margin] ELSE NULL END) as [Margin-Average] FROM MyTable

在 AVG() 函数中使用多个 case 表达式时,该列始终返回 NULL。我做错了什么?

更新: 正如@Gordon Linoff 所指出的 - 这是添加而不是聚合函数的问题。谁能提出另一种实现我想要的结果的方法?

更新: 我想要的结果:

January-Margin  February-Margin March-Margin    AvgMargin
43.111          0.00            0.00            43.111
57.2897         0.00            0.00            57.2897
55.5352         56.8987         0.00            56.2169

【问题讨论】:

  • 案例表达式。 (返回一个值。)
  • 不使用AVG函数你可以sum除以count() where values >0这样你可以跳过0个值
  • @Mark 。 . .您想要的结果不清楚。

标签: sql sql-server case average


【解决方案1】:

您应该排除 where 子句中的值。任何带有空值的操作都返回空值。

(1 + null) = null;
(1 - null) = null;
(3 + 4 + 5 + null) / 4 = null; // that's AVG function, right there

我觉得你的桌子有点奇怪。但无论如何,您都可以进行嵌套选择。

    select 
(select avg(january-margin) from table where isnull(january-margin,0) > 0) january-margin,
(select avg(february-margin) from table where isnull(february-margin,0) > 0) february-margin
from table

等等。

请注意,您可能希望与外部查询表进行一些联接。

【讨论】:

    【解决方案2】:

    嗯,我认为您可能需要替换 0。加法的问题,而不是平均值:

    AVG(CASE WHEN [January-Margin] > 0 THEN [January-Margin] ELSE 0 END +
        CASE WHEN [February-Margin] > 0 THEN [February-Margin] ELSE 0 END
       ) as [Margin-Average]
    

    如果所有内容都是0,则使用NULLIF() 忽略这些行:

    AVG(NULLIF(CASE WHEN [January-Margin] > 0 THEN [January-Margin] ELSE 0 END +
               CASE WHEN [February-Margin] > 0 THEN [February-Margin] ELSE 0 END, 0
              )
       ) as [Margin-Average]
    

    但是,您的问题中没有此类示例。

    编辑:

    你只是想要这个吗?

    (AVG(NULLIF([January-Margin], 0) + AVG(NULLIF([February-Margin], 0))) / 2
    

    这有点像不是0 的两列中的值的平均值。

    实际平均值为:

    (SUM(NULLIF([January-Margin], 0) + SUM(NULLIF([February-Margin], 0))) / (COUNT(NULLIF([January-Margin], 0)) + COUNT(NULLIF([February-Margin], 0)))
    

    【讨论】:

    • 谢谢,但是当我像你建议的那样输入零而不是 null 时,SQL 服务器会将零计为平均值的一部分,从而降低平均值 - 这是我想要避免的
    • @Mark 。 . .为此,您需要NULLIF() - 但在整个表达式上,而不是组件上。但是,您的示例数据没有两列都是0 的行,因此这不会影响。
    【解决方案3】:

    如何使用 CROSS APPLY 和 NullIf()

    示例

    Declare @YourTable Table ([January-Margin] money,[February-Margin] money,[March-Margin] money)  Insert Into @YourTable Values 
     (43.111,0,0)
    ,(57.289700,0,0)
    ,(55.535200,56.898700,0)
    
    Select A.* 
          ,B.*
     From @YourTable A
     Cross Apply ( 
                   Select AvgMargin = avg(Value)
                    From (  values (NullIf([January-Margin] ,0))
                                  ,(NullIf([February-Margin],0))
                                  ,(NullIf([March-Margin]   ,0))
                          ) B1(value)
                )B
    

    退货

    January-Margin  February-Margin March-Margin    AvgMargin
    43.111          0.00            0.00            43.111
    57.2897         0.00            0.00            57.2897
    55.5352         56.8987         0.00            56.2169
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-04-30
      • 2021-10-16
      • 1970-01-01
      • 2019-02-16
      • 1970-01-01
      • 1970-01-01
      • 2019-10-23
      相关资源
      最近更新 更多