web-dev-qa-db-ja.com

同じSELECTリストで列のエイリアスを参照する

古いMS-AccessベースのシステムをPostgreSQLに変換しています。 Accessでは、次のように、SELECTで構成されたフィールドを、後のフィールドの数式の一部として使用できます。

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

PostgreSQLでこれを行うと、Postgresがエラーをスローします。

エラー:列 "percent_water"は存在しません。

サブセレクションから選択することで、これを回避する方法は次のとおりです。

_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;
_

複雑なネストを回避するための最初のコードブロックのようなショートカットはありますか? 100 * (samples.wet_weight / samples.dry_weight - 1) AS percent_water_100と言うこともできますが、これは私のコードで実行されているはるかに大きな数学のシステムのほんの小さな例であり、数十のより複雑な数学のビットが互いに積み重ねられています。私は自分自身を繰り返さずにできるだけきれいにしたいと思います。

32
wizpig64

不便な場合もありますが、SQLの標準的な動作であり、あいまいさを防ぐことができます。同じSELECTリスト内の列エイリアスを参照することはできません。

短い構文オプションがあります:

_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;
_

また、Postgres 9.3以降ではLATERAL結合を使用できます。

_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;
_

ゼロ除算エラーを防ぐためにNULLIF()を追加しました。

27

500行以上のNetezzaクエリ(別名、変更後のPostgres)をSQL Serverに移行して、このようなものを見つけました。 Netezzaでは、計算された列のエイリアスを下流参照の値として使用できました。

私の回避策は、相関サブクエリでCROSS APPLYを使用することでした。元のクエリの列エイリアスへの多数の参照をまったく変更する必要がなかったのはすばらしいことです。

OPからのクエリを使用して、CROSS APPLYメソッドは次のようになります。

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