結果にそのような複数の行が必要な場合は、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