Alias ​​kolom referensi dalam daftar SELECT yang sama

27

Saya mengonversi sistem berbasis MS-Access lama ke PostgreSQL. Di Access, bidang yang dibuat dalam SELECT dapat digunakan sebagai bagian dari persamaan untuk bidang selanjutnya, seperti ini:

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

Ketika saya melakukan ini di PostgreSQL, Postgres melempar kesalahan:

GALAT: kolom "persen_water" tidak ada.

Inilah cara saya dapat mengatasinya, dengan memilih dari sub-pilihan:

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;

Apakah ada cara pintas seperti di blok kode pertama untuk berkeliling bersarang rumit? Saya juga bisa mengatakannya 100 * (samples.wet_weight / samples.dry_weight - 1) AS percent_water_100, tetapi ini hanyalah contoh kecil dari apa yang terjadi dengan sistem matematika yang lebih besar dalam kode saya, dengan lusinan bit matematika yang lebih rumit ditumpuk satu sama lain. Saya lebih suka melakukan sebersih mungkin tanpa mengulangi sendiri.

wizpig64
sumber

Jawaban:

24

Kadang-kadang merepotkan, tapi itu perilaku standar SQL, dan mencegah ambiguitas. Anda tidak dapat merujuk alias kolom dalam SELECTdaftar yang sama .

Ada opsi sintaks yang lebih pendek:

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;

Dan Anda dapat menggunakan LATERALgabungan di 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;

Saya menambahkan NULLIF()untuk membela terhadap kesalahan divisi-by-nol.

Erwin Brandstetter
sumber
2
Hai. Bisakah Anda memperluas jawaban Anda dengan contoh ambiguitas yang standar SQL mencegah?
Eugen Konkov
4

Saya menemukan sesuatu seperti ini, memigrasikan 500+ baris Netezza query (alias modifikasi Postgres) ke SQL Server. Di Netezza alias kolom yang dihitung diizinkan untuk digunakan sebagai nilai dalam referensi hilir.

Pekerjaan saya adalah menggunakan CROSS APPLY dengan sub-kueri yang berkorelasi. Keindahan itu adalah bahwa banyak referensi ke alias kolom dalam permintaan asli tidak perlu diubah sama sekali.

Menggunakan kueri dari OP, CROSS APPLYmetode akan terlihat seperti:

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
sumber
1
CROSS APPLY(dan OUTER BERLAKU) adalah cara SQL Server untuk menulis LATERALsubqueries.
ypercubeᵀᴹ
4
Tidak ada cross applydi Postgres. Postgres menempel pada standar dan kegunaan cross join lateral.
a_horse_with_no_name