我有其在Oracle表32列的表。
我想获得的所有值列,这是由空(身份)列复杂的平均值。 下面是什么,我想实现的伪代码:
SELECT
((nvl(val0, 0) + nvl(val1, 0) + ... nvl(valn, 0))
/ nonZero_Column_Count_In_This_Row)
使得:nonZero_Column_Count_In_This_Row =(ifNullThenZeroElse1(val0)+ ifNullThenZeroElse1(VAL1)... ifNullThenZeroElse(VALN))
这里的困难当然是在获得1对于任何非空列。 看来我需要类似NVL的功能,但有一个else子句。 东西,将返回0,如果值是零,但1如果没有,而不是本身的价值。
我应该如何去有关获取的价值为分母?
PS:我觉得我必须要解释这种设计背后的一些动力。 理论上讲,该表将被组织为身份列,并与一些标识该行本身每行一个值。 这将使它更加规范化和解决这个问题本来很简单。 不这样做的原因吧是吞吐量,并节省空间。 这是我们插入每分钟千万值成一个巨大的数据库。 使每个值一行就意味着每分钟10M行,这是绝对不能达到的。 包装有30到一行降低插入的东西,我们可以用一个DB做的行数,并且开销数据量(身份数据)少得多。
你可以使用NVL2(val0, 1, 0) + NVL2(val1, 1, 0) + ...
因为你使用的是Oracle。
另一种选择是使用AVG功能,而忽略空值:
SELECT AVG(v) FROM (
WITH q AS (SELECT val0, val1, val2, val3 FROM mytable)
SELECT val0 AS v FROM q
UNION ALL SELECT val1 FROM q
UNION ALL SELECT val2 FROM q
UNION ALL SELECT val3 FROM q
);
如果你使用Oracle11g中您可以使用UNPIVOT语法,使其更简单。
我看到这是一个很老的问题,但我没有看到足够的答案。 我有一个类似的问题,以下是我如何解决它。 这是很清楚的,需要一个case语句。 该解决方案是这样的情况下,一种解决方法
SELECT COUNT(column) WHERE column {IS | IS NOT} NULL
不因任何原因失效,或者你需要做几件
SELECT COUNT ( * )
FROM A_TABLE
WHERE COL1 IS NOT NULL;
SELECT COUNT ( * )
FROM A_TABLE
WHERE COL2 IS NOT NULL;
查询,但想把它当作一个数据集,当你运行该脚本。 见下文; 我用这个分析,它已经为我工作的伟大至今。
SUM(CASE NVL(valn, 'X')
WHEN 'X'
THEN 0
ELSE 1
END) as COLUMN_NAME
FROM YOUR_TABLE;
干杯!
道格
一般地,你可以这样做:
SELECT (
(COALESCE(val0, 0) + COALESCE(val1, 0) + ...... COALESCE(valn, 0))
/
(SIGN(ABS(COALESCE(val0, 0))) + SIGN(ABS(COALESCE(val1, 0))) + .... )
) AS MyAverage
顶线将返回值(省略NULL值),而底行的总和将返回非空值的数量。
仅供参考 - 这是SQL Server语法,但COALESCE就像ISNULL大部分。 SIGN只是返回-1为负数,0表示零,以及1的正数。 ABS是“绝对值”。