这显然是错误的,但是对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
感谢。
答案 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
诀窍是交叉连接操作,为骰子返回的每一行提供三行,以及一个表达式,每个行都会选择Die1
,Die2
和Die3
的值。分别是三行。
要排除0的值,我们将0替换为NULL(因为AVG不包含NULL值。)
现在将所有非零DieN
值堆叠到一个列中,我们可以使用AVG函数。
另一种方法是获取Die1
,Die2
,Die3
....的每一个的分子和分母,然后总计分子,总计分母,然后将总分子除以总分母。
这将给出相同的结果。
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
中没有匹配的行,Die1
,Die2
和{的所有值对于任一查询,{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}}
没有必要过度思考这个问题,问题不是太难了