Alias ​​della colonna di riferimento nello stesso elenco SELECT


27

Sto convertendo un vecchio sistema basato su MS-Access in PostgreSQL. In Access, i campi creati in SELECT potrebbero essere utilizzati come parti di equazioni per campi successivi, come questo:

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

Quando lo faccio in PostgreSQL, Postgres genera un errore:

ERRORE: la colonna "percent_water" non esiste.

Ecco come posso aggirarlo, selezionando da una sottoselezione:

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;

C'è qualche tipo di scorciatoia come nel primo blocco di codice per aggirare l'annidamento complicato? Potrei anche solo dire 100 * (samples.wet_weight / samples.dry_weight - 1) AS percent_water_100, ma questo è solo un piccolo esempio di ciò che è un sistema matematico molto più ampio nel mio codice, con dozzine di bit matematici più complessi sovrapposti l'uno sull'altro. Preferirei fare nel modo più pulito possibile senza ripetermi.

Risposte:


24

A volte è scomodo, ma è un comportamento standard SQL e impedisce le ambiguità. Non è possibile fare riferimento agli alias di colonna nello stesso SELECTelenco.

Esistono opzioni di sintassi più brevi:

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;

E puoi usare un LATERALjoin in 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;

Ho aggiunto NULLIF()per difendermi da errori di divisione per zero.


2
Ciao. Potresti estendere la tua risposta con un esempio che le ambiguità che SQL Standart impedisce?
Eugen Konkov

4

Ho colpito qualcosa del genere migrando una query Netezza di oltre 500 righe (aka Postgres modificata) su SQL Server. In Netezza è stato consentito utilizzare l'alias di colonna calcolato come valore nei riferimenti a valle.

Il mio lavoro era usare CROSS APPLY con una sottoquery correlata. Il bello è che non è stato necessario modificare i numerosi riferimenti all'alias di colonna nella query originale.

Utilizzando la query dall'OP, il CROSS APPLYmetodo sarebbe simile a:

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 ;

1
CROSS APPLY(e OUTER APPLY) è il modo SQL Server di scrivere LATERALsottoquery.
ypercubeᵀᴹ

4
Non c'è cross applyin Postgres. Postgres si attiene allo standard e agli usi cross join lateral.
a_horse_with_no_name
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.