アップデート:
LATERAL
結合はそれを可能にし、Postgres9.3で導入されました。詳細:
その理由はエラーメッセージにあります。リストの1つの要素は、同じレベルFROM
のリストの別の要素を参照できません。FROM
同じレベルのピアには表示されません。相関サブクエリでこれを解決できます:
SELECT *, (SELECT t FROM rp ORDER BY abs(rp.t - rq.t) LIMIT 1) AS ra
FROM rq
明らかに、RP
同じように近い行のセットからどの行を選択するかは気にしないので、私も同じことをします。
ただし、リスト内のサブクエリ式は1つの列SELECT
しか返すことができません。テーブルに複数またはすべての列が必要な場合は、次のサブクエリ構造のようなものを使用します。両方のテーブルに
主キーが存在すると想定します。RP
id
SELECT id, t, (ra).*
FROM (
SELECT *, (SELECT rp FROM rp ORDER BY abs(rp.t - rq.t) LIMIT 1) AS ra
FROM rq
) x;
相関するサブクエリは、パフォーマンスが悪いことで有名です。この種のクエリは、明らかに必要なものを計算しますが、式ではインデックスrp.t - rq.t
を使用できないため、特に問題が発生します。テーブルが大きくなると、パフォーマンスが大幅に低下します。
この書き直されたクエリは、上のインデックスRP.t
を利用できるはずです。これは、大きなテーブルではるかに高速に実行されるはずです。
WITH x AS (
SELECT *
,(SELECT t
FROM rp
WHERE rp.t < rq.t
ORDER BY rp.t DESC
LIMIT 1) AS t_pre
,(SELECT t
FROM rp
WHERE rp.t >= rq.t
ORDER BY rp.t
LIMIT 1) AS t_post
FROM rq
)
SELECT id, t
,CASE WHEN (t_post - t) < (t - t_pre)
THEN t_post
ELSE COALESCE(t_pre, t_post) END AS ra
FROM x;
繰り返しますが、行全体が必要な場合:
WITH x AS (
SELECT *
,(SELECT rp
FROM rp
WHERE rp.t < rq.t
ORDER BY rp.t DESC
LIMIT 1) AS t_pre
,(SELECT rp
FROM rp
WHERE rp.t >= rq.t
ORDER BY rp.t
LIMIT 1) AS t_post
FROM rq
), y AS (
SELECT id, t
,CASE WHEN ((t_post).t - t) < (t - (t_pre).t)
THEN t_post
ELSE COALESCE(t_pre, t_post) END AS ra
FROM x
)
SELECT id AS rq_id, t AS rq_t, (ra).*
FROM y
ORDER BY 2;
複合型での括弧の使用に注意してください!ここでは冗長なパレンはありません。詳細については、こちらとこちらのマニュアルをご覧ください。
PostgreSQL9.1でテスト済み。sqlfiddleのデモ。