2

単純化された構造が次のように見える 2 つのテーブルがあります。

RESPONSES
id
created

ACCESSORY VALUES
id
response_id
sensor_id
value

特定の応答のすべてのアクセサリ値を一定期間にわたって 1 つの行にフラット化するビューを作成したいと考えています ( でフィルタリングresponse.created)。ピボットテーブルまたはクロス集計が必要だと思いますが、両方に慣れておらず、見つけた例は主に既知の数の列を扱っています。さらに複雑なことに、特定のセンサーは、ユーザーが問題の時間中に追跡を開始または停止した場合、その期間の一部にしか表示されませんでした. 理想的には、センサーが存在しない場合は、センサーの列に NULL を保持します。これは可能ですか?もしそうなら、私は正しい軌道に乗っていますか、それとも間違った場所を探していますか?

個々の行としてデータを取得するSQLは次のようになります

SELECT r.id, a.sensor_id, a.value from results_response r 
INNER JOIN results_accessoryvalue a ON r.id = a.response_id
WHERE r.installation_id = 40 
AND r.created BETWEEN '2013-04-01' AND '2013-05-01' 
ORDER BY r.created

しかし、動的列を指定する方法がわからないため、クロス集計で使用しようとしてもうまくいきません。

4

2 に答える 2

3

クロスタブをいくつかのアドオンで使用する必要があります。私もこの問題を抱えていて、このような私の提案のためにそれを解決しました。

最初にクロス集計拡張機能をインストールする

私が使用したトリックは、2 つの追加関数を作成することです。クロス集計関数の結果セットとして必要なタイプ情報を取得するためのもの。これを見てください:

CREATE OR REPLACE FUNCTION "TEMPORARY.TYPE.FROM.COLUMN"(text, text)
  RETURNS text AS
$BODY$
DECLARE
    typestring TEXT;
    returnrec RECORD;
BEGIN
    typestring := '';
    FOR returnrec IN EXECUTE $1 LOOP
        typestring := typestring||', "'||returnrec."Column"||'" '||$2;
    END LOOP;

  RETURN typestring;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;

これで、2 番目の関数を記述できます。

CREATE OR REPLACE FUNCTION "DYNAMIC.CROSSTAB"(text, text, text)
  RETURNS text AS
$BODY$
DECLARE
    typestring TEXT;
    executestring TEXT;
BEGIN
    DROP TABLE IF EXISTS "TBL.Crosstab";
    SELECT "REPORTING"."TEMPORARY.TYPE.FROM.COLUMN"($2,$3) INTO typestring;
    executestring := 'CREATE TEMPORARY TABLE "TBL.Crosstab" AS (SELECT * FROM crosstab('''||$1||''','''||$2||''') AS (row_name DATE'||typestring||'));';
    EXECUTE executestring;
  RETURN '"TBL.Crosstab"';
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;

クロス集計を作成するには、次のように呼び出します。

SELECT * FROM "DYNAMIC.CROSSTAB"(text, text, text);

結果が入力されたセッションの一時テーブルの名前を返します。このように必要でした。

パラメータの説明:

First = データを取得するためのクエリ (row_name、cat、value の 3 つの列が必要です)

2 番目 = すべてのカテゴリを返す列を取得するクエリ (cat)

3 番目 = 一時的な型の columntype

完璧ではありませんが、私たちのニーズに合っています。この方法で 450 列以上と数千行をフェッチするステートメントがあります。それが役に立てば幸い

于 2013-05-15T10:49:54.393 に答える
0

これは PostgreSQL 配列を使用した代替アプローチです

create table responses (
    id serial not null  unique,
    x   integer,
    created timestamp default now()
);

 create table accessory (
    id serial not null,
    responses_id integer references responses (id),
    sensor_id  integer,
    value text,
    created timestamp default now()
);

insert into responses  (x) values  ( 1), (2),(3),(4);

insert into accessory  (responses_id ,  sensor_id, value ) values  
( 1, 1, 'A' ), ( 1, 2, 'Ab' ),  ( 1, 3, 'Ac' ),  ( 1, 4, 'Ad' ),
( 2, 4, 'Ab' ), ( 1, 2, 'bAb' ),  ( 3, 3, 'bAc' ),  ( 4, 4, 'bAd' );

select *, array(
    select value
    from accessory
    where accessory.responses_id  = responses.id  
    order by  accessory.created
    ) as accessory_values
from responses;

クエリ結果には、response.id に一致するすべてのアクセサリ値を含む配列列が含まれます

于 2013-05-10T18:13:10.137 に答える