古い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
と言うこともできますが、これは私のコードで実行されているはるかに大きな数学のシステムのほんの小さな例であり、数十のより複雑な数学のビットが互いに積み重ねられています。私は自分自身を繰り返さずにできるだけきれいにしたいと思います。
不便な場合もありますが、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()
を追加しました。
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 ;