PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

ERRO:a subconsulta em FROM não pode se referir a outras relações de mesmo nível de consulta

Atualização:


LATERAL joins permitem isso e foram introduzidos com o Postgres 9.3. Detalhes:

O motivo está na mensagem de erro. Um elemento do FROM list não pode se referir a outro elemento do FROM lista no mesmo nível. Não é visível para um par no mesmo nível. Você pode resolver isso com uma subconsulta correlacionada :
SELECT *, (SELECT t FROM rp ORDER BY abs(rp.t - rq.t) LIMIT 1) AS ra
FROM   rq

Obviamente, você não se importa com qual linha de RP você escolhe de um conjunto de linhas igualmente próximas, então eu faço o mesmo.

No entanto, uma expressão de subconsulta no SELECT list só pode retornar um coluna. Se você quiser mais de uma ou todas as colunas da tabela RP , use algo como esta construção de subconsulta:
Presumo a existência de uma chave primária id em ambas as tabelas.
SELECT id, t, (ra).*
FROM (
    SELECT *, (SELECT rp FROM rp ORDER BY abs(rp.t - rq.t) LIMIT 1) AS ra
    FROM   rq
    ) x;

As subconsultas correlacionadas são famosas por desempenho ruim . Esse tipo de consulta - enquanto obviamente calcula o que você deseja - será sugar em particular, porque a expressão rp.t - rq.t não pode usar um índice. O desempenho se deteriorará drasticamente com mesas maiores.

Esta consulta reescrita deve ser capaz de utilizar um índice em RP.t , que deve ter um desempenho muito mais rápido com 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;

Novamente, se você quiser a linha inteira:
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;

Observe o uso de parênteses com tipos compostos ! Nenhum parêntese é redundante aqui. Mais sobre isso no manual aqui e aqui .

Testado com PostgreSQL 9.1. Demonstração no sqlfiddle.