【问题标题】:Get AVG ignoring Null or Zero values获取忽略 Null 或零值的 AVG
【发布时间】:2013-06-29 18:52:44
【问题描述】:

如何获得忽略 NULL 和零值的列的 AVG

我有三列来获取它们的平均值,我尝试使用以下脚本:

SELECT distinct
     AVG(cast(ISNULL(a.SecurityW,0) as bigint)) as Average1
     ,AVG(cast(ISNULL(a.TransferW,0) as bigint)) as Average2
     ,AVG(cast(ISNULL(a.StaffW,0) as bigint)) as Average3
FROM Table1 a,  Table2 b
WHERE a.SecurityW <> 0 AND a.SecurityW IS NOT NULL
AND a.TransferW<> 0 AND a.TransferWIS NOT NULL
AND a.StaffW<> 0 AND a.StaffWIS NOT NULL
AND MONTH(a.ActualTime) = 4
AND YEAR(a.ActualTime) = 2013

我没有得到任何结果,但是这三列的值包括 NULL 和零!

在获取平均值之前是否有排除空值的方法?

示例:AVERAGE(NOTNULL(SecurityW))

【问题讨论】:

  • 所有这些ANDs 意味着您只会获得在所有 3 列中具有非 NULL 值的行。此外,您的NOT NULL 检查不是必需的,因为如果ColumnNULLColumn&lt;&gt;0 的计算结果为UNKNOWN

标签: sql sql-server tsql sql-server-2008-r2


【解决方案1】:

NULL 已被忽略,因此您可以使用NULLIF0 转换为NULL。此外,您不需要DISTINCT 并且您在ActualTime 上的WHERE 是不可搜索的。

SELECT AVG(cast(NULLIF(a.SecurityW, 0) AS BIGINT)) AS Average1,
       AVG(cast(NULLIF(a.TransferW, 0) AS BIGINT)) AS Average2,
       AVG(cast(NULLIF(a.StaffW, 0) AS BIGINT))    AS Average3
FROM   Table1 a
WHERE  a.ActualTime >= '20130401'
       AND a.ActualTime < '20130501' 

PS 我不知道 Table2 b 在原始查询中是什么,因为它没有连接条件,所以在我的回答中省略了它。

【讨论】:

  • 顺便说一句,我不认为你通过将整数转换为 bigint 来实现任何目标
  • @t-clausen.dk - 如果SUM 太大,它可以防止算术溢出错误。 SELECT AVG(C) FROM (SELECT 2147483647 UNION ALL SELECT 2147483647) T(C) 失败,但 SELECT AVG(CAST(C AS BIGINT)) FROM (SELECT 2147483647 UNION ALL SELECT 2147483647) T(C) 成功。
  • @DanielGimenez 您的解决方案目前没有正确忽略 0。这个答案确实使用 nullif。
  • @DanielGimenez - 不会。试试吧。 SELECT AVG(NULLIF(C,0)) FROM (SELECT 30 UNION ALL SELECT null UNION ALL SELECT 0) T(C) 返回30
【解决方案2】:

这应该可以,但还没有尝试过。这将排除零。默认排除NULL

AVG (CASE WHEN SecurityW <> 0 THEN SecurityW ELSE NULL END)

【讨论】:

    【解决方案3】:

    如果在平均函数中不考虑“0”或“NULL”。 只需使用

    AVG(NULLIF(your_column_name,0))
    

    【讨论】:

      【解决方案4】:

      为我工作:

      AVG(CASE WHEN SecurityW <> 0 THEN SecurityW ELSE NULL END)
      

      【讨论】:

        【解决方案5】:

        您已经尝试使用NOT NULL 过滤掉NULL 值。我已在WHERE 子句中将其更改为IS NOT NULL,以便执行。我们可以通过删除AVG 方法中的ISNULL 函数来重构它。另外,我怀疑你是否真的需要bigint,这样我们才能移除演员表。

        SELECT distinct
             AVG(a.SecurityW) as Average1
             ,AVG(a.TransferW) as Average2
             ,AVG(a.StaffW) as Average3
        FROM Table1 a,  Table2 b
        WHERE a.SecurityW <> 0 AND a.SecurityW IS NOT NULL
        AND a.TransferW<> 0 AND a.TransferWIS IS NOT NULL
        AND a.StaffW<> 0 AND a.StaffWIS IS NOT NULL
        AND MONTH(a.ActualTime) = 4
        AND YEAR(a.ActualTime) = 2013
        

        【讨论】:

          【解决方案6】:

          Null 值无论如何都会从平均值计算中排除。如果您还需要排除零值,您可以简单地在 avg 函数中使用 decode 函数:-

          SELECT AVG(decode(a.SecurityW,0,null,a.SecurityW)) as Average1
           ,AVG(decode(a.TransferW,0,null,a.TransferW)) as Average2
           ,AVG(decode(a.StaffW,0,null,a.StaffW)) as Average3 
          FROM Table1 a,  Table2 b
          WHERE MONTH(a.ActualTime) = 4
          AND YEAR(a.ActualTime) = 2013;
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-07-17
            • 1970-01-01
            • 2013-04-11
            • 2020-12-10
            • 1970-01-01
            • 2020-05-19
            • 1970-01-01
            • 2019-03-30
            相关资源
            最近更新 更多