【问题标题】:How to: MYSQL average from multiple columns excluding Null Values and Changing Number Divided By如何:来自多个列的 MYSQL 平均值,不包括 Null 值和更改的数字除以
【发布时间】:2018-08-01 18:19:45
【问题描述】:

使用以下 MySQL 5.6 查询 SELECT sum(col1 + col2 + col3) / 3 AS Result FROM table1

我怎样才能做同样的事情只忽略 NULL 值? 另外,调整除以数字减去 NULL 值?

我们的实验室使用感官面板来评估我们产品的某些质量点。 每个小组成员对每个样本的评分为 -1、0 或 1。 对于任何给定的样本,我们可以将 1 到 15 个分数平均为“结果”。

参考问题 #24398431

下面是我刚刚测试的查询。我没有收到任何错误,但根本没有收到任何数据。我会尽我所能获得帮助。

SELECT ndx, t_stamp, fv, name, lot, Pnl1, Pnl2, Pnl3, Pnl4, Pnl5, Pnl6, Pnl7, 
Pnl8, Pnl9, Pnl10, 
((sum((CASE WHEN (Pnl1 IS NOT NULL) THEN Pnl1 ELSE 0 END)
+(CASE WHEN (Pnl2 IS NOT NULL) THEN Pnl2 ELSE 0 END)
+(CASE WHEN (Pnl3 IS NOT NULL) THEN Pnl3 ELSE 0 END)
+(CASE WHEN (Pnl4 IS NOT NULL) THEN Pnl4 ELSE 0 END)
+(CASE WHEN (Pnl5 IS NOT NULL) THEN Pnl5 ELSE 0 END)
+(CASE WHEN (Pnl6 IS NOT NULL) THEN Pnl6 ELSE 0 END)
+(CASE WHEN (Pnl7 IS NOT NULL) THEN Pnl7 ELSE 0 END)
+(CASE WHEN (Pnl8 IS NOT NULL) THEN Pnl8 ELSE 0 END)
+(CASE WHEN (Pnl9 IS NOT NULL) THEN Pnl9 ELSE 0 END)
+(CASE WHEN (Pnl10 IS NOT NULL) THEN Pnl10 ELSE 0 END)))
/
(sum((CASE WHEN (Pnl1 IS NOT NULL) THEN 1 ELSE 0 END)
+(CASE WHEN (Pnl2 IS NOT NULL) THEN 1 ELSE 0 END)
+(CASE WHEN (Pnl3 IS NOT NULL) THEN 1 ELSE 0 END)
+(CASE WHEN (Pnl4 IS NOT NULL) THEN 1 ELSE 0 END)
+(CASE WHEN (Pnl5 IS NOT NULL) THEN 1 ELSE 0 END)
+(CASE WHEN (Pnl6 IS NOT NULL) THEN 1 ELSE 0 END)
+(CASE WHEN (Pnl7 IS NOT NULL) THEN 1 ELSE 0 END)
+(CASE WHEN (Pnl8 IS NOT NULL) THEN 1 ELSE 0 END)
+(CASE WHEN (Pnl9 IS NOT NULL) THEN 1 ELSE 0 END)
+(CASE WHEN (Pnl10 IS NOT NULL) THEN 1 ELSE 0 END)))) AS Result
FROM vdk
WHERE Pnl1 IS NOT NULL AND Pnl2 IS NOT NULL AND Pnl3 IS NOT NULL AND Pnl4 IS 
NOT NULL AND Pnl5 IS NOT NULL
AND Pnl6 IS NOT NULL AND Pnl7 IS NOT NULL AND Pnl8 IS NOT NULL AND Pnl9 IS 
NOT NULL AND Pnl10 IS NOT NULL
AND t_stamp Between "{Root Container.Brew Harvest Table.brewTable.StartTime}" 
AND "{Root Container.Brew Harvest Table.brewTable.EndTime}"

好的,将所有 AND 更改为 OR 就可以了,所以我返回了一行数据,根据输入的数据应该返回 7 行。 如果我运行相同的查询减去 sum case 部分,我会返回所有 7 行。 以下是当前查询。我错过了什么,为什么只有一行数据?

SELECT ndx, t_stamp, fv, name, lot, Pnl1, Pnl2, Pnl3, Pnl4, Pnl5, Pnl6, Pnl7, 
Pnl8, Pnl9, Pnl10, 
((sum((CASE WHEN (Pnl1 IS NOT NULL) THEN Pnl1 ELSE 0 END)
+(CASE WHEN (Pnl2 IS NOT NULL) THEN Pnl2 ELSE 0 END)
+(CASE WHEN (Pnl3 IS NOT NULL) THEN Pnl3 ELSE 0 END)
+(CASE WHEN (Pnl4 IS NOT NULL) THEN Pnl4 ELSE 0 END)
+(CASE WHEN (Pnl5 IS NOT NULL) THEN Pnl5 ELSE 0 END)
+(CASE WHEN (Pnl6 IS NOT NULL) THEN Pnl6 ELSE 0 END)
+(CASE WHEN (Pnl7 IS NOT NULL) THEN Pnl7 ELSE 0 END)
+(CASE WHEN (Pnl8 IS NOT NULL) THEN Pnl8 ELSE 0 END)
+(CASE WHEN (Pnl9 IS NOT NULL) THEN Pnl9 ELSE 0 END)
+(CASE WHEN (Pnl10 IS NOT NULL) THEN Pnl10 ELSE 0 END)))
/
(sum((CASE WHEN (Pnl1 IS NOT NULL) THEN 1 ELSE 0 END)
+(CASE WHEN (Pnl2 IS NOT NULL) THEN 1 ELSE 0 END)
+(CASE WHEN (Pnl3 IS NOT NULL) THEN 1 ELSE 0 END)
+(CASE WHEN (Pnl4 IS NOT NULL) THEN 1 ELSE 0 END)
+(CASE WHEN (Pnl5 IS NOT NULL) THEN 1 ELSE 0 END)
+(CASE WHEN (Pnl6 IS NOT NULL) THEN 1 ELSE 0 END)
+(CASE WHEN (Pnl7 IS NOT NULL) THEN 1 ELSE 0 END)
+(CASE WHEN (Pnl8 IS NOT NULL) THEN 1 ELSE 0 END)
+(CASE WHEN (Pnl9 IS NOT NULL) THEN 1 ELSE 0 END)
+(CASE WHEN (Pnl10 IS NOT NULL) THEN 1 ELSE 0 END)))) AS Result
FROM vdk
WHERE Pnl1 IS NOT NULL OR Pnl2 IS NOT NULL OR Pnl3 IS NOT NULL OR Pnl4 IS 
NOT NULL OR Pnl5 IS NOT NULL
OR Pnl6 IS NOT NULL OR Pnl7 IS NOT NULL OR Pnl8 IS NOT NULL OR Pnl9 IS 
NOT NULL OR Pnl10 IS NOT NULL
AND t_stamp Between "{Root Container.Brew Harvest Table.brewTable.StartTime}" 
AND "{Root Container.Brew Harvest Table.brewTable.EndTime}"

【问题讨论】:

  • 所以你想要每行的平均值不为空值的总和?
  • 正如我在下面的答案中评论的那样,您可能应该使用 OR not AND;但是您可以通过COALESCE(col1, col2, col3, and so on ) IS NOT NULL 使其更简洁。 COALESCE 返回第一个非空值;如果全部为空,则为空。

标签: mysql null average


【解决方案1】:

SQL 中经常使用的一种简单方法是case 语句。您可以使用 case 语句计算 col1、col2 和 col3 以查看它们是否为空,然后输出 col1/2/3 值(用于分子)或 1 或 0 作为分母。

MySQL 可能有特定的函数来帮助解决这个问题(例如,case 语句可以用 if 函数重写),但大多数 RDBMS 都理解 case

这是一个示例,说明您可以如何做到这一点 - 我已经扩展了分子和分母,以便更清楚地了解正在发生的事情。

select
    (
        -- Numerator (output col1/2/3 value when not null)
        sum
        (
            -- col1
            (case when (col1 is not null) then col1 else 0 end)
            -- col2
            + (case when (col2 is not null) then col2 else 0 end)
            -- col3
            + (case when (col3 is not null) then col3 else 0 end)
        )
        /
        -- Denominator
        sum
        (
            -- col1
            (case when (col1 is not null) then 1 else 0 end)
            -- col2
            + (case when (col2 is not null) then 1 else 0 end)
            -- col3
            + (case when (col3 is not null) then 1 else 0 end)
        )
    ) as Result
from
    table1
where
    col1 is not null
    or col2 is not null
    or col3 is not null

需要注意的几点:

  • 我已经包含了一个 where 子句来排除 col1、col2 和 col3 为空的任何行。这是为了防止分母为 0,否则会导致除以 0 错误。如果您返回 sum 列(除非表中的所有行都只有空值),则不需要这样做,但是一旦您将另一列添加到您的选择列列表中,那么它将为每一行评估此Result 列,因此您要确保不会拉出任何可能导致除以零错误的内容。考虑“我的查询是否可以除以零”问题,并与查询的执行成本进行平衡(如果 col1/col2/col3 上没有索引,那么您可能会看到选择性能下降)

  • 1234563或分母浮动。基本思路是,如果sum的值被确定为int的值,那么MySQL会“将一个int除以一个int”,结果的数据类型也将是一个int。但是,如果您将 int 除以 float(或 float 除以 int),则结果将是 float 数据类型。

【讨论】:

  • 实际上,如果所有行都只有空值,则应该只存在被零除的问题。 虽然我不完全确定这会计算出 OP 正在寻找的值。
  • @Uueerdo 谢谢,很好的观察。我将编辑答案,以明确只有当查询还包含其他列时才会出现除以零的问题。
  • 感谢您的帮助。我是这方面的真正菜鸟。
  • 另一个注意事项:AND 只允许完全没有 NULL 值的行,而不是至少有一个非 NULL 值的行;应该使用 OR。
  • @Uueerdo 再次感谢您指出这一点!它已在答案中得到纠正。正如您对 OP 的评论所指出的那样,coalesce 在这里会很有用,但我想让答案相对容易理解,并且 RDBMS 中立。
【解决方案2】:

下面的查询给了我想要的结果。 谢谢 RToyo 和 Uueerdo,如果没有你们的帮助,我将无法完成这项工作。

SELECT ndx, t_stamp,fv, name, lot, TankTmp, gcBut, gcPent, (gcBut+gcPent) AS gcTot,
gcIntStHx, gcExtbut, gcExtpent, gcExtrsp, (gcBut*2) AS histBut, (gcPent*2) AS 
histPent, ((gcBut*2)+(gcPent*2)) AS histTot,
Initial, Pnl1, Pnl2, Pnl3, Pnl4, Pnl5, Pnl6, Pnl7, Pnl8, Pnl9, Pnl10,
(((CASE WHEN (Pnl1 IS NOT NULL) THEN Pnl1 ELSE 0 END)
+(CASE WHEN (Pnl2 IS NOT NULL) THEN Pnl2 ELSE 0 END)
+(CASE WHEN (Pnl3 IS NOT NULL) THEN Pnl3 ELSE 0 END)
+(CASE WHEN (Pnl4 IS NOT NULL) THEN Pnl4 ELSE 0 END)
+(CASE WHEN (Pnl5 IS NOT NULL) THEN Pnl5 ELSE 0 END)
+(CASE WHEN (Pnl6 IS NOT NULL) THEN Pnl6 ELSE 0 END)
+(CASE WHEN (Pnl7 IS NOT NULL) THEN Pnl7 ELSE 0 END)
+(CASE WHEN (Pnl8 IS NOT NULL) THEN Pnl8 ELSE 0 END)
+(CASE WHEN (Pnl9 IS NOT NULL) THEN Pnl9 ELSE 0 END)
+(CASE WHEN (Pnl10 IS NOT NULL) THEN Pnl10 ELSE 0 END))
/
((CASE WHEN (Pnl1 IS NOT NULL) THEN 1 ELSE 0 END)
+(CASE WHEN (Pnl2 IS NOT NULL) THEN 1 ELSE 0 END)
+(CASE WHEN (Pnl3 IS NOT NULL) THEN 1 ELSE 0 END)
+(CASE WHEN (Pnl4 IS NOT NULL) THEN 1 ELSE 0 END)
+(CASE WHEN (Pnl5 IS NOT NULL) THEN 1 ELSE 0 END)
+(CASE WHEN (Pnl6 IS NOT NULL) THEN 1 ELSE 0 END)
+(CASE WHEN (Pnl7 IS NOT NULL) THEN 1 ELSE 0 END)
+(CASE WHEN (Pnl8 IS NOT NULL) THEN 1 ELSE 0 END)
+(CASE WHEN (Pnl9 IS NOT NULL) THEN 1 ELSE 0 END)
+(CASE WHEN (Pnl10 IS NOT NULL) THEN 1 ELSE 0 END))) AS Result,
note
FROM vdk
WHERE t_stamp Between "{Root Container.Brew Harvest Table.brewTable.StartTime}" 
AND "{Root Container.Brew Harvest Table.brewTable.EndTime}"
ORDER BY t_stamp ASC

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-04
    • 2021-02-08
    • 1970-01-01
    • 2019-04-03
    • 1970-01-01
    • 2014-09-06
    相关资源
    最近更新 更多