Псевдонім посилання стовпців у цьому ж списку SELECT


27

Я перетворюю стару систему на основі MS-Access в PostgreSQL. В Access поля, складені в SELECTs, можуть використовуватися як частини рівнянь для пізніших полів, таких як:

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

Коли я це роблю в PostgreSQL, Postgres видає помилку:

ПОМИЛКА: стовпець "відсоток води" не існує.

Ось як я можу обійти його, вибравши підбірку:

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?
Євген Конков

4

Я потрапив на щось подібне до цього, переміщаючи запит Netezza на 500+ (також модифікований Postgres) на SQL Server. У Netezza обчислений псевдонім стовпця було дозволено використовувати як значення в посиланнях нижче.

Моя робота полягала в тому, щоб використовувати CROSS APPLY з відповідним підзапитом. Краса в тому, що численні посилання на псевдонім стовпця в оригінальному запиті взагалі не потребували змін.

Використовуючи запит з ОП, 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(та OUTER APPLY) - спосіб LATERALзапиту підзапитів на SQL Server .
ypercubeᵀᴹ

4
У cross applyПостгресі немає . Postgres дотримується стандарту та використовує cross join lateral.
a_horse_with_no_name
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.