2

タイムスタンプ付きのいくつかのレコードの PostgreSQL データベースがあります。

ある期間 (たとえば、PRECEDING 式と FOLLOWING 式を使用して 1 か月) にウィンドウ内のデータを収集し、その月のすべてのレコードを含む複数の列 (たとえば、月の各日に対して 30) を作成する簡単な方法はありますか?

この単純なケースを考えてみましょう: 2 つの列timestampとのテーブルですmeasurement。私が欲しいのは、31列のテーブルを取得することです:タイムスタンプとmeasurement1measurement2... measurement30、ここで、measurement_iタイムスタンプのi日前の測定値です。

4

1 に答える 1

1

結果にそのような複数の行が必要な場合は、crosstab()関数を使用します。

しかし、あなたの説明によると、単一の行が必要です。ウィンドウ関数lead()またはlag().
主なトリックは、サブクエリまたは CTE を使用してすべての列を生成してから、WHERE 句を適用して結果を 1 行に絞り込むことです。ここでCTEを使用します。

次の表が与えられた場合 (提供する必要があります):

CREATE TABLE tbl(
  tbl_id serial PRIMARY KEY
 ,ts timestamp NOT NULL
 ,value int
);

1日1行保証

クエリは次のようになります。

WITH x AS (
   SELECT tbl_id, ts, value
         ,lag(value, 1) OVER w AS value_day_before_1
         ,lag(value, 2) OVER w AS value_day_before_2
   --    ...
         ,lead(value, 1) OVER w AS value_day_after_1
         ,lead(value, 2) OVER w AS value_day_after_2
   --    ...
   FROM   tbl
   WINDOW w AS (ORDER BY ts) 
   )
SELECT *
FROM   x
WHERE  ts = '2013-02-14 0:0'::timestamp

1 日あたり最大で 1 行ですが、日数が欠落している可能性があります。

また、タイムスタンプは 1 日のいつでも指定できます。

generate_series()とそれにLEFT JOINあなたのテーブルで日のリストを生成します。

WITH x AS (
   SELECT tbl_id, ts, value
         ,lag(value, 1) OVER w AS value_day_before_1
         ,lag(value, 2) OVER w AS value_day_before_2
   --    ...
         ,lead(value, 1) OVER w AS value_day_after_1
         ,lead(value, 2) OVER w AS value_day_after_2
   --    ...
   FROM   (
       SELECT generate_series ('2013-02-01'::date
                              ,'2013-02-28'::date
                              ,interval '1d') AS day
       ) d
   LEFT JOIN tbl t ON date_trunc('day', t.ts) = d.day
   WINDOW w AS (ORDER BY day) 
   )
SELECT *
FROM   x
WHERE  ts = '2013-02-14 0:0'::timestamp;

->sqlfiddle

于 2013-02-19T16:58:48.903 に答える