PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

BŁĄD:podzapytanie w FROM nie może odnosić się do innych relacji tego samego poziomu zapytania

Aktualizacja:

LATERAL złącza pozwalają na to i zostały wprowadzone w Postgresie 9.3. Szczegóły:

Powód znajduje się w komunikacie o błędzie. Jeden element FROM lista nie może odnosić się do innego elementu FROM lista na tym samym poziomie. Nie jest widoczny dla osoby równorzędnej na tym samym poziomie. Możesz rozwiązać ten problem za pomocą skorelowanego podzapytania :

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

Oczywiście nie obchodzi Cię, który wiersz z RP wybierasz z zestawu równie bliskich rzędów, więc robię to samo.

Jednak wyrażenie podzapytania w SELECT lista może zwrócić tylko jeden kolumna. Jeśli chcesz więcej niż jedną lub wszystkie kolumny z tabeli RP , użyj czegoś takiego jak ta konstrukcja podzapytania:
Zakładam istnienie klucza podstawowego id w obu tabelach.

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

Skorelowane podzapytania są niesławne z powodu złej wydajności . Tego rodzaju zapytania – choć oczywiście obliczają, czego chcesz – będą do dupy w szczególności dlatego, że wyrażenie rp.t - rq.t nie może używać indeksu. Wydajność ulegnie drastycznemu pogorszeniu przy większych stołach.

To przepisane zapytanie powinno być w stanie wykorzystać indeks na RP.t , który powinien wykonać dużo szybciej z dużymi stołami .

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;

Ponownie, jeśli chcesz cały rząd:

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;

Zwróć uwagę na użycie nawiasów z typami złożonymi ! Żaden rodzic nie jest tutaj zbędny. Więcej na ten temat w instrukcji tutaj i tutaj .

Testowane z PostgreSQL 9.1. Demo na sqlfiddle.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Zezwalaj tylko na role listy użytkowników postgres

  2. Jak przyspieszyć działanie wstawiania w PostgreSQL

  3. Wygeneruj SQL, aby zaktualizować klucz podstawowy

  4. Dlaczego planista przedstawia różne wyniki dla funkcji o różnych zmiennościach?

  5. Wyłączyć DELETE w tabeli w PostgreSQL?