it-swarm.com.de

Referenzspaltenalias in derselben SELECT-Liste

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

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

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

FEHLER: Spalte "Prozent_Wasser" existiert nicht.

So kann ich es umgehen, 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 auch einfach 100 * (samples.wet_weight / samples.dry_weight - 1) AS percent_water_100 sagen, aber dies ist nur ein kleines Beispiel aus einem viel größeren mathematischen System in meinem Code, in dem Dutzende komplexerer mathematischer Teile übereinander gestapelt sind . Ich würde es vorziehen, so sauber wie möglich zu sein, ohne mich zu wiederholen.

32
wizpig64

Es ist manchmal unpraktisch, aber es ist SQL-Standardverhalten und verhindert Mehrdeutigkeiten. Sie können nicht auf Spaltenaliasnamen in derselben SELECT -Liste 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 LATERAL Join 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 habe NULLIF() hinzugefügt, um mich gegen Fehler durch Division durch Null zu verteidigen.

27

Ich habe so etwas getroffen, als ich eine Netezza-Abfrage mit mehr als 500 Zeilen (auch bekannt als modifiziertes Postgres) auf SQL Server migriert habe. In Netezza durfte der berechnete Spaltenalias als Wert in nachgeschalteten Referenzen verwendet werden.

Meine Arbeit 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.

Unter Verwendung der Abfrage aus dem OP wird das CROSS APPLY Methode würde 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 ;
5
D Turpin