PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

ERREUR :la sous-requête dans FROM ne peut pas faire référence à d'autres relations du même niveau de requête

Mise à jour :

LATERAL les jointures le permettent et ont été introduites avec Postgres 9.3. Détails :

La raison est dans le message d'erreur. Un élément du FROM la liste ne peut pas faire référence à un autre élément du FROM liste au même niveau. Il n'est pas visible pour un pair au même niveau. Vous pouvez résoudre ce problème avec une sous-requête corrélée :

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

De toute évidence, vous ne vous souciez pas de la ligne de RP vous choisissez parmi un ensemble de lignes également proches, donc je fais de même.

Cependant, une expression de sous-requête dans le SELECT la liste ne peut en renvoyer qu'un colonne. Si vous voulez plus d'une ou toutes les colonnes de la table RP , utilisez quelque chose comme cette construction de sous-requête :
Je suppose l'existence d'une clé primaire id dans les deux tableaux.

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

Les sous-requêtes corrélées sont tristement célèbres pour leurs mauvaises performances . Ce genre de requête - tout en calculant évidemment ce que vous voulez - va crainer notamment parce que l'expression rp.t - rq.t ne peut pas utiliser un index. Les performances se détérioreront considérablement avec des tables plus grandes.

Cette requête réécrite devrait pouvoir utiliser un index sur RP.t , qui devrait être beaucoup performant plus rapide avec de grandes tables .

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;

Encore une fois, si vous voulez toute la ligne :

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;

Notez l'utilisation de parenthèses avec les types composites ! Aucune parenthèse n'est redondante ici. Plus d'informations à ce sujet dans le manuel ici et ici .

Testé avec PostgreSQL 9.1. Démo sur sqlfiddle.