PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

FEHLER:Unterabfrage in FROM kann nicht auf andere Relationen derselben Abfrageebene verweisen

Aktualisierung:

LATERAL Joins erlauben dies und wurden mit Postgres 9.3 eingeführt. Einzelheiten:

Der Grund steht in der Fehlermeldung. Ein Element des FROM list kann nicht auf ein anderes Element von FROM verweisen Liste auf der gleichen Ebene. Es ist für einen Peer auf derselben Ebene nicht sichtbar. Sie könnten dies mit einer korrelierten Unterabfrage lösen :

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

Offensichtlich ist es Ihnen egal, welche Zeile aus RP stammt Sie wählen aus einer Reihe gleich enger Reihen aus, also mache ich dasselbe.

Allerdings ein Unterabfrageausdruck im SELECT list kann nur eine zurückgeben Säule. Wenn Sie mehr als eine oder alle Spalten aus der Tabelle RP wünschen , verwenden Sie so etwas wie dieses Unterabfragekonstrukt:
Ich gehe davon aus, dass ein Primärschlüssel id existiert in beiden Tabellen.

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

Korrelierte Unterabfragen sind berüchtigt für schlechte Leistung . Diese Art von Abfrage - während sie offensichtlich berechnet, was Sie wollen - wird beschissen sein insbesondere, weil der Ausdruck rp.t - rq.t kann keinen Index verwenden. Bei größeren Tabellen verschlechtert sich die Leistung drastisch.

Diese umgeschriebene Abfrage sollte in der Lage sein, einen Index auf RP.t zu verwenden , die viel leisten sollte schneller mit großen Tischen .

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;

Nochmals, wenn Sie die ganze Reihe wollen:

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;

Beachten Sie die Verwendung von Klammern bei zusammengesetzten Typen ! Hier ist kein Elternteil überflüssig. Mehr dazu im Handbuch hier und hier .

Getestet mit PostgreSQL 9.1. Demo auf sqlfiddle.