sql >> Databáze >  >> RDS >> PostgreSQL

CHYBA:poddotaz ve FROM nemůže odkazovat na jiné vztahy stejné úrovně dotazu

Aktualizace:

LATERAL připojení to umožňují a byly představeny s Postgres 9.3. Podrobnosti:

Důvod je v chybové zprávě. Jeden prvek FROM seznam nemůže odkazovat na jiný prvek FROM seznam na stejné úrovni. Není viditelný pro peer na stejné úrovni. Můžete to vyřešit pomocí korelovaného poddotazu :

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

Je zřejmé, že je vám jedno, který řádek z RP vybíráte ze sady stejně blízkých řad, takže já udělám totéž.

Nicméně výraz poddotazu v SELECT seznam může vrátit pouze jeden sloupec. Pokud chcete více než jeden nebo všechny sloupce z tabulky RP , použijte něco jako tento konstrukt poddotazu:
Předpokládám existenci primárního klíče id v obou tabulkách.

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

Korelované poddotazy jsou nechvalně známé pro špatný výkon . Tento druh dotazu – i když zjevně počítá, co chcete – bude našlápnutý zejména proto, že výraz rp.t - rq.t nelze použít index. S většími stoly se výkon drasticky zhorší.

Tento přepsaný dotaz by měl být schopen využívat index na RP.t , která by měla vystupovat hodně rychlejší u velkých stolů .

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;

Znovu, pokud chcete celý řádek:

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;

Všimněte si použití závorek u složených typů ! Žádný rodič zde není nadbytečný. Více o tom v manuálu zde a zde .

Testováno s PostgreSQL 9.1. Ukázka na sqlfiddle.



  1. získání hodnoty ze sloupce, ale vrátí hodnotu null?

  2. Jak Round() funguje v PostgreSQL

  3. Optimalizace aktualizačních dotazů

  4. A.* není ve skupině GROUP BY s levým spojením na laravel query builderu