Alias ​​kolumny odniesienia na tej samej liście WYBIERZ

27

Konwertuję stary system oparty na MS-Access na PostgreSQL. W programie Access pola utworzone w SELECT mogą być używane jako części równań dla późniejszych pól, takich jak to:

SELECT
    samples.id,
    samples.wet_weight / samples.dry_weight - 1 AS percent_water,
    100 * percent_water AS percent_water_100
FROM samples;

Kiedy robię to w PostgreSQL, Postgres zgłasza błąd:

BŁĄD: kolumna „percent_water” nie istnieje.

Oto jak mogę to obejść, wybierając z podselekcji:

SELECT
    s1.id,
    s1.percent_water,
    100 * s1.percent_water AS percent_water_100
FROM (
    SELECT
        samples.id,
        samples.wet_weight / samples.dry_weight - 1 AS percent_water
    FROM samples
    ) s1;

Czy jest jakiś skrót, jak w pierwszym bloku kodu, aby obejść skomplikowane zagnieżdżanie? Mógłbym również powiedzieć 100 * (samples.wet_weight / samples.dry_weight - 1) AS percent_water_100, ale to tylko mały przykład z tego, co w moim kodzie jest o wiele większym systemem matematycznym, z dziesiątkami bardziej złożonych bitów matematyki ułożonych jeden na drugim. Wolałbym robić tak czysto, jak to możliwe, bez powtarzania się.

wizpig64
źródło

Odpowiedzi:

24

Czasami jest to niewygodne, ale jest to standardowe zachowanie SQL i zapobiega dwuznacznościom. Nie można odwoływać się do aliasów kolumn na tej samej SELECTliście.

Istnieją krótsze opcje składni:

SELECT s.*, s.percent_water * 100 AS percent_water_100
FROM  (
   SELECT id, wet_weight / NULLIF(dry_weight - 1, 0) AS percent_water
   FROM   samples
   ) s;

I możesz użyć LATERALzłączenia w Postgres 9.3+:

SELECT s.id, s1.percent_water
     , s1.percent_water * 100 AS percent_water_100
FROM   samples s
     , LATERAL (SELECT s.wet_weight / NULLIF(s.dry_weight - 1, 0) AS percent_water) s1;

Dodałem, NULLIF()aby bronić się przed błędami dzielenia przez zero.

Erwin Brandstetter
źródło
2
Cześć. Czy możesz rozszerzyć swoją odpowiedź o przykład, który zapobiega dwuznacznościom standardu SQL?
Eugen Konkov
4

Uderzyłem coś takiego, migrując ponad 500-wierszowe zapytanie Netezza (inaczej zmodyfikowany Postgres) do SQL Server. W Netezza pozwolono na użycie obliczonego aliasu kolumny jako wartości w dalszych odnośnikach.

Moje zadanie polegało na użyciu aplikacji CROSS APPLY ze skorelowanym zapytaniem cząstkowym. Piękno tego polega na tym, że liczne odniesienia do aliasu kolumny w oryginalnym zapytaniu wcale nie musiały być zmieniane.

Przy użyciu zapytania z PO CROSS APPLYmetoda mogłaby wyglądać mniej więcej tak:

SELECT
    s.id,
    x.percent_water,
    100 * x.percent_water AS percent_water_100
FROM samples AS s
CROSS APPLY (SELECT s.wet_weight / s.dry_weight - 1 AS percent_water ) x ;
D Turpin
źródło
1
CROSS APPLY(i ZEWNĘTRZNE ZASTOSOWANIE) to SQL Server sposób pisania LATERALpodkwerend.
ypercubeᵀᴹ
4
Nie ma cross applyw Postgres. Postgres trzyma się standardu i zastosowań cross join lateral.
a_horse_w_no_name