Alias ​​der Referenzspalte in derselben SELECT-Liste

27

Ich konvertiere ein altes MS-Access-basiertes System nach PostgreSQL. In Access können Felder, die in SELECTs erstellt wurden, als Teile von Gleichungen für spätere Felder verwendet werden.

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

Wenn ich das in PostgreSQL mache, gibt Postgres einen Fehler aus:

FEHLER: Spalte "Prozent_Wasser" existiert nicht.

Hier ist, wie ich es umgehen kann, indem ich aus einer Unterauswahl auswähle:

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;

Gibt es eine Verknüpfung wie im ersten Codeblock, um komplizierte Verschachtelungen zu umgehen? Ich könnte es auch so sagen 100 * (samples.wet_weight / samples.dry_weight - 1) AS percent_water_100, aber dies ist nur ein kleines Beispiel für ein viel größeres mathematisches System in meinem Code, bei dem Dutzende komplexerer mathematischer Teile übereinander gestapelt sind. Ich würde es vorziehen, so sauber wie möglich zu arbeiten, ohne mich zu wiederholen.

wizpig64
quelle

Antworten:

24

Es ist manchmal unbequem, aber es ist ein SQL-Standardverhalten und es verhindert Mehrdeutigkeiten. Sie können nicht auf Spaltenaliasnamen in derselben SELECTListe verweisen .

Es gibt kürzere Syntaxoptionen:

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;

Und Sie können einen LATERALJoin in Postgres 9.3+ verwenden:

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;

Ich fügte hinzu NULLIF(), um mich gegen Fehler durch Division durch Null zu verteidigen.

Erwin Brandstetter
quelle
2
Hallo. Können Sie Ihre Antwort um ein Beispiel erweitern, das Unklarheiten verhindert, die der SQL-Standard aufweist?
Eugen Konkov
4

Ich bin auf so etwas gestoßen, als ich eine über 500 Zeilen lange Netezza-Abfrage (auch als modifiziertes Postgres bezeichnet) nach SQL Server migriert habe. In Netezza durfte der berechnete Spaltenalias als Wert in nachgelagerten Referenzen verwendet werden.

Meine Aufgabe bestand darin, CROSS APPLY mit einer korrelierten Unterabfrage zu verwenden. Das Schöne daran ist, dass die zahlreichen Verweise auf den Spaltenalias in der ursprünglichen Abfrage überhaupt nicht geändert werden mussten.

Mit der Abfrage aus dem OP CROSS APPLYwürde die Methode ungefähr so ​​aussehen:

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
quelle
1
CROSS APPLY(und OUTER APPLY) ist die SQL Server-Methode zum Schreiben von LATERALUnterabfragen.
ypercubeᵀᴹ
4
Es gibt keine cross applyin Postgres. Postgres hält sich an den Standard und verwendet cross join lateral.
a_horse_with_no_name