我正在寻找一个优雅的查询来获得平均忽略零值。
示例:我有2个值和预期结果:
SELECT X(10,20) AS result
-- expected result: 15
SELECT X(0,20) AS result
-- expected result: 20
SELECT X(10,0) AS result
-- expected result: 10
SELECT X(0,0) AS result
-- expected result: NULL
这是我的尝试:
(val1+val2)/(2-IF(val1,0,1)-IF(val2,0,1))
有更好的方法吗?
谢谢
答案 0 :(得分:2)
我这样写:
( val1 + val2 )/( ABS(SIGN(val1)) + ABS(SIGN(val2)) )
我相信这相当于OP表达,它已经看起来像没有创建用户定义函数那样优雅。
(这真的只是我个人的偏好,以避免减去常数" 2"和额外的" 1"和#34; 0"常数。)
如果我必须将此表达式扩展为三个参数:
( val1 + val2 + val3)/( ABS(SIGN(val1)) + ABS(SIGN(val2)) + ABS(SIGN(val3)) )
注意:
MySQL SIGN
函数将返回一个整数值,表示"符号"数值:-1
,0
,1
或NULL
。
MySQL ABS
函数将返回一个数字的绝对值,因此将其包围在SIGN函数周围,即ABS(SIGN(n))
返回将为0
,1
或{ {1}}。 NULL
会返回相同的内容。
如果其中一个参数为NULL,则此表达式将返回NULL。就像OP表达式一样。
我不确定那更优雅。但那是我怎么做的。
如果目的是缩短SQL,只需指定SIGN(ABS(n))
和val1
一次,如在OP示例中那样,需要一个函数。 MySQL没有为此提供本机内置函数,因此我们必须定义(创建)用户定义的函数。
但是如果我们这样做,我们需要指定参数的数据类型和返回的数据类型(例如val2
,BIGINT
,DECIMAL(M,N)
等等。我们采用这种方式,它有可能进行隐式数据类型转换和舍入/不精确。
如果没有用户定义的函数,DOUBLE
和val1
必须在表达式中包含两次。但我认为,在其他一些提议的表达方式中,这比每次的四到五次要好。
答案 1 :(得分:1)
在平均之前,使用CASE
来处理其中一列为0
的情况。
SELECT CASE
WHEN val1 = 0 AND val2 = 0 THEN NULL
WHEN val1 = 0 OR val2 = 0 THEN val1 + val2
ELSE (val1+val2)/2
END AS avg
答案 2 :(得分:1)
select case when val1 = 0 and val2= 0 then null
when val1 = 0 and val2 ! = 0 then val2
when val1 != 0 and val2= 0 then val1
else (val1 + val2 ) /2
end avg
尝试根据您的要求或mysql版本进行修改