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


27

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

回答:


24

時々不便ですが、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;

またLATERAL、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;

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


2
こんにちは。SQLの標準が防止する曖昧さの例によって答えを拡張できますか?
Eugen Konkov

4

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 ;

1
CROSS APPLY(および外部適用)は、SQL ServerでLATERALサブクエリを記述する方法です。
ypercubeᵀᴹ

4
cross applyPostgresにはありません。Postgresは標準に準拠して使用しcross join lateralます。
a_horse_with_no_name
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.