นามแฝงคอลัมน์อ้างอิงในรายการ SELECT เดียวกัน


27

ฉันกำลังแปลงระบบเก่าที่ใช้ MS-Access เป็น PostgreSQL ในการเข้าถึงเขตข้อมูลที่สร้างขึ้นใน 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 SQL ป้องกันได้หรือไม่?
Eugen Konkov

4

ฉันตีบางอย่างเช่นนี้การโยกย้ายแบบสอบถาม 500 บรรทัด Netezza (aka Postgres ที่แก้ไขแล้ว) ไปยัง SQL Server ใน Netezza นามแฝงคอลัมน์ที่คำนวณได้รับอนุญาตให้ใช้เป็นค่าในการอ้างอิงแบบดาวน์สตรีม

การทำงานของฉันคือการใช้ CROSS ใช้กับแบบสอบถามย่อยที่มีความสัมพันธ์ ความสวยงามของมันคือการอ้างอิงจำนวนมากไปยังนามแฝงคอลัมน์ในข้อความค้นหาต้นฉบับไม่จำเป็นต้องเปลี่ยนเลย

ใช้แบบสอบถามจาก 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 applyใน Postgres Postgres cross join lateralแท่งมาตรฐานและการใช้งาน
a_horse_with_no_name
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.