PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

ERRORE:la sottoquery in FROM non può fare riferimento ad altre relazioni dello stesso livello di query

Aggiornamento:

LATERAL i join lo consentono e sono stati introdotti con Postgres 9.3. Dettagli:

Il motivo è nel messaggio di errore. Un elemento del FROM list non può fare riferimento a un altro elemento del FROM lista allo stesso livello. Non è visibile per un peer dello stesso livello. Potresti risolverlo con una sottoquery correlata :

SELECT *, (SELECT t FROM rp ORDER BY abs(rp.t - rq.t) LIMIT 1) AS ra
FROM   rq

Ovviamente, non ti interessa quale riga da RP scegli da un insieme di righe ugualmente vicine, quindi faccio lo stesso.

Tuttavia, un'espressione di sottoquery in SELECT list può restituire solo uno colonna. Se vuoi più di una o tutte le colonne della tabella RP , usa qualcosa come questo costrutto di sottoquery:
Presumo l'esistenza di una chiave primaria id in entrambe le tabelle.

SELECT id, t, (ra).*
FROM (
    SELECT *, (SELECT rp FROM rp ORDER BY abs(rp.t - rq.t) LIMIT 1) AS ra
    FROM   rq
    ) x;

Le sottoquery correlate sono famigerate per scarso rendimento . Questo tipo di query, mentre ovviamente calcola quello che vuoi, succhia in particolare, perché l'espressione rp.t - rq.t non è possibile utilizzare un indice. Le prestazioni si deterioreranno drasticamente con i tavoli più grandi.

Questa query riscritta dovrebbe essere in grado di utilizzare un indice su RP.t , che dovrebbe avere un rendimento molto più veloce con tavoli grandi .

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;

Di nuovo, se vuoi l'intera riga:

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;

Nota l'uso di parentesi con tipi compositi ! Nessun genitore è ridondante qui. Maggiori informazioni su questo nel manuale qui e qui .

Testato con PostgreSQL 9.1. Demo su sqlfiddle.