MySQL查询平均3列并排除0' s?

时间:2017-03-01 01:48:25

标签: mysql

这显然是错误的,但是对3列的SUM进行平均并排除0的正确方法是什么?

SELECT ( 
    AVG(NULLIF(`dices`.`Die1`,0)) + 
    AVG(NULLIF(`dices`.`Die2`,0)) + 
    AVG(NULLIF(`dices`.`Die3`,0)) 
) /3  as avgAllDice 
FROM (
    SELECT `Die1`,`Die2`,`Die3` FROM `GameLog` 
    WHERE PlayerId = "12345"
) dices

感谢。

2 个答案:

答案 0 :(得分:0)

如果我保留内联视图查询(它不清楚为什么需要它)。我可能会这样做:

SELECT AVG( NULLIF( CASE d.i
                    WHEN 1 THEN dices.`Die1`
                    WHEN 2 THEN dices.`Die2` 
                    WHEN 3 THEN dices.`Die3`
                    END
            ,0)
       ) AS `avgAllDice`
  FROM ( SELECT gl.`Die1`
              , gl.`Die2`
              , gl.`Die3`
           FROM `GameLog` gl 
          WHERE gl.playerId = '12345'
       ) dices
 CROSS
  JOIN ( SELECT 1 AS i UNION ALL SELECT 2 UNION ALL SELECT 3 ) d

诀窍是交叉连接操作,为骰子返回的每一行提供三行,以及一个表达式,每个行都会选择Die1Die2Die3的值。分别是三行。

要排除0的值,我们将0替换为NULL(因为AVG不包含NULL值。)

现在将所有非零DieN值堆叠到一个列中,我们可以使用AVG函数。

另一种方法是获取Die1Die2Die3 ....的每一个的分子和分母,然后总计分子,总计分母,然后将总分子除以总分母。

这将给出相同的结果。

SELECT ( IFNULL(t.n_die1,0) + IFNULL(t.n_die2,0) + IFNULL(t.n_die3,0) )
     / (        t.d_die1    +        t.d_die2    +        t.d_die3    )
       AS avgAllDice 
  FROM ( SELECT SUM(  NULLIF(gl.die1,0))   AS n_die1
              , COUNT(NULLIF(gl.die1,0))   AS d_die1
              , SUM(  NULLIF(gl.die2,0))   AS n_die2
              , COUNT(NULLIF(gl.die2,0))   AS d_die2
              , SUM(  NULLIF(gl.die3,0))   AS n_die3
              , COUNT(NULLIF(gl.die3,0))   AS d_die3
           FROM `GameLog` gl
          WHERE gl.playerid = '12345'
       ) t

(我没有弄清楚在边缘和角落情况下返回的内容...... GameLog中没有匹配的行,Die1Die2和{的所有值对于任一查询,{1}}为零等。结果可能略有不同,返回零而不是NULL,除以零边缘情况等。)

<强>后续

我对两个查询进行了快速测试。

Die3

manual_avg即将发布3.2。

两个查询也都返回3.2

答案 1 :(得分:0)

如果要消除零和NULL,可以多次从过滤后的主集中UNION ALL,对结果执行SELECT AVG(`allDice`.`DieResult`) FROM ( SELECT `Die1` AS `DieResult` FROM `GameLog` WHERE COALESCE(`Die1`, 0) <> 0 AND PlayerId = '12345' UNION ALL SELECT `Die2` FROM `GameLog` WHERE COALESCE(`Die2`, 0) <> 0 AND PlayerId = '12345' UNION ALL SELECT `Die3` FROM `GameLog` WHERE COALESCE(`Die3`, 0) <> 0 AND PlayerId = '12345' ) AS `allDice` ,然后对其进行平均。

{{1}}

没有必要过度思考这个问题,问题不是太难了