1

我有一个在 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 子句。如果值为 null,则返回 0,否则返回 1,而不是值本身。

我应该如何获得分母的价值?


PS:我觉得我必须解释一下这个设计背后的一些动机。理想情况下,该表将被组织为标识列和每行一个值,并带有行本身的一些标识符。这会使它更加规范化,并且该问题的解决方案将非常简单。不这样做的原因是吞吐量和节省空间。这是一个巨大的数据库,我们每分钟向其中插入 1000 万个值。将这些值中的每一个设为一行将意味着每分钟 1000 万行,这绝对是无法实现的。将其中的 30 个打包成一行可以减少插入到我们可以使用单个 DB 执行的操作的行数,并且开销数据量(身份数据)要少得多。

4

5 回答 5

2

(情况当 col 为 null 然后 0 else 1 end)

于 2009-06-19T01:10:47.353 回答
1

您可以使用NVL2(val0, 1, 0) + NVL2(val1, 1, 0) + ...,因为您使用的是 Oracle。

于 2009-06-19T01:14:50.917 回答
1

另一种选择是使用忽略 NULL 的 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 语法使其更加简单。

于 2009-06-19T01:27:11.547 回答
1

我看到这是一个很老的问题,但我没有看到足够的答案。我有一个类似的问题,下面是我如何解决它。很明显需要一个案例陈述。此解决方案是一种解决方法,适用于以下情况

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;


干杯!
道格

于 2014-01-20T15:01:05.163 回答
0

通常,您可以执行以下操作:

SELECT (
       (COALESCE(val0, 0) + COALESCE(val1, 0) + ...... COALESCE(valn, 0))
       /
       (SIGN(ABS(COALESCE(val0, 0))) + SIGN(ABS(COALESCE(val1, 0))) + .... )
       ) AS MyAverage

顶行将返回值的总和(省略 NULL 值),而底行将返回非 null 值的数量。

仅供参考 - 它是 SQL Server 语法,但 COALESCE 在大多数情况下就像 ISNULL 一样。SIGN 只返回 -1 表示负数,0 表示零,1 表示正数。ABS是“绝对值”。

于 2009-06-19T01:21:35.943 回答