Aktualizace:
LATERAL
připojení to umožňují a byly představeny s Postgres 9.3. Podrobnosti:
Důvod je v chybové zprávě. Jeden prvek FROM
seznam nemůže odkazovat na jiný prvek FROM
seznam na stejné úrovni. Není viditelný pro peer na stejné úrovni. Můžete to vyřešit pomocí korelovaného poddotazu :
SELECT *, (SELECT t FROM rp ORDER BY abs(rp.t - rq.t) LIMIT 1) AS ra
FROM rq
Je zřejmé, že je vám jedno, který řádek z RP
vybíráte ze sady stejně blízkých řad, takže já udělám totéž.
Nicméně výraz poddotazu v SELECT
seznam může vrátit pouze jeden sloupec. Pokud chcete více než jeden nebo všechny sloupce z tabulky RP
, použijte něco jako tento konstrukt poddotazu:
Předpokládám existenci primárního klíče id
v obou tabulkách.
SELECT id, t, (ra).*
FROM (
SELECT *, (SELECT rp FROM rp ORDER BY abs(rp.t - rq.t) LIMIT 1) AS ra
FROM rq
) x;
Korelované poddotazy jsou nechvalně známé pro špatný výkon . Tento druh dotazu – i když zjevně počítá, co chcete – bude našlápnutý zejména proto, že výraz rp.t - rq.t
nelze použít index. S většími stoly se výkon drasticky zhorší.
Tento přepsaný dotaz by měl být schopen využívat index na RP.t
, která by měla vystupovat hodně rychlejší u velkých stolů .
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;
Znovu, pokud chcete celý řádek:
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;
Všimněte si použití závorek u složených typů ! Žádný rodič zde není nadbytečný. Více o tom v manuálu zde a zde .
Testováno s PostgreSQL 9.1. Ukázka na sqlfiddle.