5

N列のテーブルがあります。c1それらを , c2, c3, c4, ...と呼びましょうcNCOUNT DISTINCT(cX)複数の行のうち、[1, N] の各 X で単一の行を取得したい。

c1 | c2 | ... | cn
0  | 4  | ... | 1

すべての列名を手動でクエリに書き込むことなく、(ストアド プロシージャで) これを行う方法はありますか?

なんで?

アプリケーション サーバーのバグが原因で、適切な列の値を書き直し、後でガベージを挿入するという問題がありました。これを解決するために、各行が論理UPDATEクエリを表す情報ログ構造を保存しています。次に、記録が完了したというシグナルが与えられると、値が (誤って) 上書きされたかどうかを判断できます。

複数の行にある 1 つの正しいレコードの例: 各列に多くても 1 つの値があります。

| id | initialize_time | start_time | end_time |
| 1  | 12:00am         | NULL       | NULL     |
| 1  | 12:00am         | 1:00pm     | NULL     |
| 1  | 12:00am         | NULL       | 2:00pm   |

Reconciled row:
| 1  | 12:00am         | 1:00pm     | 2:00pm   |

検出したい相容れないレコードの例:

| id | initialize_time | start_time | end_time |
| 1  | 12:00am         | NULL       | NULL     |
| 1  | 12:00am         | 1:00pm     | NULL     |
| 1  | 9:00am          | 1:00pm     | 2:00pm   |   -- New initialize time => irreconcilable!
4

1 に答える 1

3

そのためには動的SQLが必要です。つまり、関数を作成するか、DOコマンドを実行する必要があります。後者から直接値を返すことはできないため、plpgsql関数は次のようになります。

CREATE OR REPLACE function f_count_all(_tbl text
                           , OUT columns text[], OUT counts bigint[])
  RETURNS record LANGUAGE plpgsql AS
$func$
BEGIN

EXECUTE (
    SELECT 'SELECT
     ARRAY[' || string_agg('''' || quote_ident(attname) || '''', ', ') || '], 
     ARRAY[' || string_agg('count(' || quote_ident(attname) || ')', ', ') || ']
    FROM ' || _tbl
    FROM   pg_attribute
    WHERE  attrelid = _tbl::regclass
    AND    attnum  >= 1           -- exclude tableoid & friends (neg. attnum)
    AND    attisdropped is FALSE  -- exclude deleted columns
    GROUP  BY attrelid
    )
INTO columns, counts;

END
$func$;

電話:

SELECT * FROM f_count_all('myschema.mytable');

戻り値:

columns       | counts
--------------+--------
{c1, c2, c3,} | {17 1,0}

動的SQLに関する詳細な説明とリンク、およびこの関連する質問、またはSOに関するその他の質問については、この調査をEXECUTE試してください

この質問と非常によく似ています:
postgresql-テーブルの各列のカウント(null値なし)

ポリモーフィックレコードタイプを返して単一の列を動的に取得することもできますが、それはかなり複雑で高度です。おそらくあなたのケースにはあまりにも多くの努力が必要です。この関連する回答の詳細。

于 2012-12-07T15:58:23.357 に答える