1

Oracle テーブルに 32 列のテーブルがあります。

  • これらの列のうち 2 つは ID 列です
  • 残りは値です

すべての値列の平均を取得したいと思いますが、これは null (ID) 列によって複雑になります。以下は、私が達成しようとしているものの擬似コードです。

    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))

ここでの難しさはもちろん、null 以外の列に対して 1 を取得することです。NVL に似た関数が必要なようですが、else 句が必要です。値自体ではなく、値が null の場合は 0 を返し、そうでない場合は 1 を返すもの。

分母の値を取得するにはどうすればよいですか?


PS: このデザインの背後にある動機を説明しなければならないと感じています。理想的には、このテーブルは ID 列として編成され、行ごとに 1 つの値が行自体の識別子と共に構成されていました。これにより、より正規化され、この問題の解決策は非常に簡単になります。このようにしない理由は、スループットとスペースの節約です。これは、毎分 1000 万の値を挿入する巨大な DB です。これらの値をそれぞれ 1 行にすると、1 分あたり 1,000 万行になり、これは絶対に達成できません。それらの 30 個を 1 つの行にパックすると、挿入される行の数が 1 つの DB でできることを減らし、オーバーヘッド データ量 (ID データ) がはるかに少なくなります。

4

5 に答える 5

2

(col が null の場合は 0、それ以外は 1 end)

于 2009-06-19T01:10:47.353 に答える
1

もう 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 に答える
1

Oracleを使用しているため、使用できNVL2(val0, 1, 0) + NVL2(val1, 1, 0) + ...ます。

于 2009-06-19T01:14:50.917 に答える
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 に答える