2012-12-07 14 views
5

私はN列のテーブルを持っています。 c1c2c3c4、... cNとしましょう。複数の行の中で、[1、N]の各Xに対してCOUNT DISTINCT(cX)という単一の行を取得したいとします。列を一覧表示せずに、すべての列で同じ集計を実行する方法は?

すべての列名をクエリに手動で書き込まずに(ストアドプロシージャ内で)実行できる方法はありますか?

なぜですか?

アプリケーションサーバーのバグが、あとで挿入されるガベージを使用して適切な列の値を書き直すという問題がありました。これを解決するために、私は情報ログ構造を保存しています。各行は論理的な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! 
+0

列名を取得する方法、または集計を行う方法を尋ねていますか? –

+0

私は列名をフェッチする方法を知っていますが、クエリの各列名の周りの式を展開する方法はわかりません。 私のストアドプロシージャでDISTINCT(c1)、COUNT DISTINCT(c2)、...、COUNT DISTINCT(cN)FROM ... 'を避けたいです。 –

+0

これはもちろん、動的SQLで行うことができます。ちなみに、Xはどれくらい大きいですか? – dezso

答えて

3

あなたが関数を作成またはDOコマンドを実行する必要があることを意味する、そのために、動的SQLを必要としています。あなたは後者から直接値を返すことはできませんので、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についてのリンクEXECUTEthis related questionに、またはここでさらにSOをtry this serachにしてください。この質問に非常に類似し


postgresql - count (no null values) of each column in a table

あなたも試してみて、動的に単一の列を取得するための多型レコード型を返しますが、それはかなり複雑で高度なのですができます。おそらくあなたの場合にはあまりにも多くの努力。 this related answerの詳細。

関連する問題