web-dev-qa-db-ja.com

複数の行を単一の行に統合する

PostgreSQL 9.5では、reportsという名前のテーブルがあります。

CREATE TABLE public.reports (
  id BIGSERIAL PRIMARY KEY,
  id_station character(11) NOT NULL,
  date date NOT NULL,
  element character(4) NOT NULL,
  value smallint NOT NULL
);

各ステーション(id_station列)および毎日(date列)、I mayには複数の値タイプがあります(要素列):TMINTMAXTAVG(これらの値が存在しない場合があります:特定の日のTMINTMAXしかありません)。

これは(偽の)サンプルです:

22;"FR069029001";"1925-01-01";"TMAX";130
23;"FR069029001";"1925-01-01";"TMIN";-25
24;"FR069029001";"1925-01-01";"TAVG";0

これらの値を、次の表を使用して、各ステーションおよび毎日の1つの行に統合したいと思います。

CREATE TABLE public.reports_con (
id SERIAL PRIMARY KEY,
id_station character(11) NOT NULL,
date date NOT NULL,
tmin smallint,
tmax smallint,
tavg smallint
);

私はこの結果を達成したいと思います:

454;"FR069029001";"1925-01-01";-25;130;0

このようにPostgreSQLでデータを統合する方法は? CREATE TABLE AS

私はそれが次のような再帰クエリでなければならないことを知っています(人間の言語):

For each day:
    For each station:
        Find values for TMIN, TMAX, TAVG
Insert the results in reports_con in a single row with day and station

私はSQLの学習を開始し、PostgreSQL内でこれを実現したいと思います(Pythonまたはプログラミング言語ではできません)。手伝ってくれませんか?

5
Comic

ターゲットテーブルが明らかに存在するため、_CREATE TABLE AS_はソリューションとは無関係です。また、再帰的なクエリも必要ありません。

たった3つの列に対して、条件付き集計を使用できます。

_INSERT INTO reports_con (id_station, date, tmin, tmax, tavg)
SELECT id_station, date
     , min(value) FILTER (WHERE element = 'TMIN') AS tmin
     , min(value) FILTER (WHERE element = 'TMAX') AS tmax
     , min(value) FILTER (WHERE element = 'TAVG') AS tavg
FROM   reports
GROUP  BY id_station, date
ORDER  BY id_station, date;
_

集計FILTER句にはPostgres 9.4が必要です。古いバージョンの詳細と代替:

多数の行の列を増やす(およびパフォーマンスを向上させる必要がある)場合は、実際のcrosstab()クエリを検討してください。特別な問題は、keyが2つの列で構成されていることですが、onecrosstab()の場合。これらの関連する回答のように、row_number()を使用して代理キーを生成します。

3