Bí danh cột tham chiếu trong cùng danh sách CHỌN


27

Tôi đang chuyển đổi một hệ thống dựa trên MS-Access cũ sang PostgreSQL. Trong Access, các trường được tạo thành trong CHỌN có thể được sử dụng làm các phần của phương trình cho các trường sau này, như sau:

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

Khi tôi làm điều này trong PostgreSQL, Postgres sẽ gặp lỗi:

LRI: cột "Perc_water" không tồn tại.

Đây là cách tôi có thể làm việc xung quanh nó, bằng cách chọn ra một lựa chọn phụ:

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;

Có bất kỳ loại phím tắt như trong khối mã đầu tiên để có được xung quanh lồng nhau phức tạp? Tôi cũng có thể nói 100 * (samples.wet_weight / samples.dry_weight - 1) AS percent_water_100, nhưng đây chỉ là một ví dụ nhỏ trong số một hệ thống toán học lớn hơn đang diễn ra trong mã của tôi, với hàng tá các bit toán học phức tạp xếp chồng lên nhau. Tôi muốn làm sạch nhất có thể mà không cần lặp lại.

Câu trả lời:


24

Đôi khi điều đó thật bất tiện, nhưng đó là hành vi tiêu chuẩn SQL và nó ngăn ngừa sự mơ hồ. Bạn không thể tham chiếu các bí danh cột trong cùng một SELECTdanh sách.

Có các tùy chọn cú pháp ngắn hơn:

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;

Và bạn có thể sử dụng một LATERALtham gia trong 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;

Tôi đã thêm vào NULLIF()để bảo vệ chống lại các lỗi chia nhỏ.


2
Chào. Bạn có thể mở rộng câu trả lời của mình bằng một ví dụ mà sự mơ hồ mà SQL không thể ngăn chặn?
Eugen Konkov

4

Tôi đã nhấn một cái gì đó như thế này khi di chuyển một truy vấn Netezza hơn 500 dòng (còn gọi là Postgres đã sửa đổi) sang SQL Server. Trong Netezza, bí danh cột được tính toán được phép sử dụng làm giá trị trong các tham chiếu xuôi dòng.

Công việc của tôi là sử dụng CROSS ỨNG DỤNG với truy vấn phụ tương quan. Cái hay của nó là rất nhiều tham chiếu đến bí danh cột trong truy vấn ban đầu hoàn toàn không cần phải thay đổi.

Sử dụng truy vấn từ OP, CROSS APPLYphương thức sẽ trông giống như:

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(và OUTER ỨNG DỤNG) là cách SQL Server viết LATERALcác truy vấn con.
ypercubeᵀᴹ

4
Không có cross applytrong Postgres. Postgres dính vào tiêu chuẩn và sử dụng cross join lateral.
a_horse_with_no_name
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.