sql >> Base de Datos >  >> RDS >> PostgreSQL

ERROR:la subconsulta en FROM no puede referirse a otras relaciones del mismo nivel de consulta

Actualización:

LATERAL las uniones lo permiten y se introdujeron con Postgres 9.3. Detalles:

La razón está en el mensaje de error. Un elemento del FROM la lista no puede hacer referencia a otro elemento del FROM lista en el mismo nivel. No es visible para un par en el mismo nivel. Puede resolver esto con una subconsulta correlacionada :

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

Obviamente, no te importa qué fila desde RP eliges de un conjunto de filas igualmente cercanas, así que hago lo mismo.

Sin embargo, una expresión de subconsulta en SELECT la lista solo puede devolver uno columna. Si desea más de una o todas las columnas de la tabla RP , use algo como esta construcción de subconsulta:
Asumo la existencia de una clave principal id en ambas tablas.

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

Las subconsultas correlacionadas son famosas por mal rendimiento . Este tipo de consulta, aunque obviamente calcula lo que desea, apestará en particular, porque la expresión rp.t - rq.t no puede usar un índice. El rendimiento se deteriorará drásticamente con tablas más grandes.

Esta consulta reescrita debería poder utilizar un índice en RP.t , que debería rendir mucho más rápido con mesas grandes .

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;

Nuevamente, si desea la fila completa:

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;

Tenga en cuenta el uso de paréntesis con tipos compuestos ! Ningún padre es redundante aquí. Más sobre eso en el manual aquí y aquí .

Probado con PostgreSQL 9.1. Demostración en sqlfiddle.