ฉันสามารถกำหนดค่าเริ่มต้นสำหรับการเข้าร่วมด้านนอกด้านซ้ายได้หรือไม่


21

สมมติว่าฉันมีตาราง a (พร้อมคอลัมน์ a1) และ b (กับคอลัมน์ b1 และ b2) และฉันดำเนินการเข้าร่วมด้านนอกด้านซ้าย

SELECT *
FROM a LEFT OUTER JOIN b
ON a.a1 = b.b1

จากนั้น b1 และ b2 จะเป็น NULL โดยที่ค่า a1 ไม่มีค่าที่ตรงกันของ b1

ฉันสามารถให้ค่าเริ่มต้นสำหรับ b2 แทน NULL ได้หรือไม่? หมายเหตุที่เชื่อมต่อกันจะไม่ทำงานที่นี่เพราะผมไม่ต้องการให้ค่าเริ่มต้นที่จะแทนที่ NULLs ศักยภาพใน B2 ที่มีเป็นค่าของการจับคู่ a1 b1

นั่นคือด้วยและ a เป็น

CREATE TABLE a (a1)
  AS VALUES (1),
            (2),
            (3) ;

CREATE TABLE b (b1,b2)
  AS VALUES (1, 10),
            (3, null) ;


a1     b1 | b2
---    --------
 1      1 | 10
 2      3 | NULL
 3

และค่าเริ่มต้นสำหรับ b2 ของ, พูด, 100, ฉันต้องการได้ผลลัพธ์

a1 | b1   | b2
---------------
1  |  1   | 10
2  | NULL | 100
3  |  3   | NULL

ในกรณีง่ายๆนี้ฉันสามารถทำ "ด้วยมือ" โดยดูว่า b1 เป็น NULL ในผลลัพธ์ นั่นเป็นตัวเลือกที่ดีที่สุดโดยทั่วไปหรือมีวิธีมาตรฐานและแบบ neater มากกว่าหรือไม่

คำตอบ:


23
SELECT a.a1,b.b1,  
    CASE WHEN b.b1 is NULL THEN 5 ELSE b.b2 END AS b2  
FROM a LEFT OUTER JOIN b  
ON a.a1 = b.b1

2
กรุณาใช้ ANSI SQL เมื่อคำถามถูกแท็กด้วยเท่านั้นsql(ซึ่งหมายถึง "SQL ภาษาคิวรี" แท็กนั้นไม่ได้หมายถึงผลิตภัณฑ์ DBMS เฉพาะหรือภาษาถิ่น) ส่วน: [b2]=CASE WHEN ... ENDเป็นนิพจน์ SQL ที่ไม่ถูกต้อง (มาตรฐาน)
a_horse_with_no_name

ฉันได้เพิ่มแท็กเพื่อระบุว่าฉันจะยอมรับคำตอบเฉพาะของ Postgres ยังคงต้องการ SQL มาตรฐานถ้าเป็นไปได้
Tom Ellis

@ คิน: ตามที่ระบุไว้ในคำถามของฉันฉันรู้ว่า "ฉันสามารถทำได้" ด้วยมือ "โดยดูว่า b1 เป็น NULL ในผลลัพธ์หรือไม่นั่นเป็นตัวเลือกที่ดีที่สุดโดยทั่วไปหรือมีวิธีมาตรฐานมากกว่า
Tom Ellis

3
เนื่องจากคุณต้องการแยกความแตกต่างระหว่างค่า NULL ที่เกิดขึ้นเนื่องจากการเข้าร่วมและสิ่งที่มีอยู่ "ตามธรรมชาติ" มันเป็นสิ่งที่หลีกเลี่ยงไม่ได้ที่คุณจะต้องตรวจสอบ b1 หากนั่นคือสิ่งที่คุณหมายถึงโดย "ฉันสามารถทำได้" ด้วยมือ "" มากกว่าใช่นั่นเป็นวิธีเดียวเท่านั้น
Mordechai

@MorDeror: ตกลงฉันคิดว่าฉันคิดว่าอาจมีไวยากรณ์เช่น "ซ้ายเข้าร่วม ... เปิด ... เริ่มต้น b2 = ... "
Tom Ellis

2

คำตอบเดิมสำหรับคำถามนี้ยังไม่ได้อธิบายดังนั้นให้ลองถ่ายอีกครั้ง

ใช้CASEคำสั่ง

การใช้วิธีนี้เราใช้ประโยชน์จากการที่เรามีค่าอื่นในคอลัมน์ที่แตกต่างกันซึ่งIS NOT NULLในกรณีนี้b.b1ถ้าค่านั้นเป็นโมฆะเราก็รู้ว่าการเข้าร่วมล้มเหลว

SELECT
  a.a1,
  b.b1,  
  CASE WHEN b.b1 is NULL THEN 100 ELSE b.b2 END AS b2  
FROM a
LEFT OUTER JOIN b  
  ON (a.a1 = b.b1);

ทั้งหมดนี้จะทำงานและสร้างสิ่งที่คุณต้องการ

ใช้ sub-SELECT

อย่าใช้วิธีนี้มันเป็นความคิดที่สะสม อ่านต่อไป

หากเราไม่มีNOT NULLคอลัมน์ใด ๆที่เราสามารถใช้ประโยชน์เช่นนั้นได้เราต้องการสิ่งที่จะสร้างคอลัมน์ที่สามารถทำงานในแบบที่เรา ...

SELECT
  a.a1,
  b.b1,  
  CASE WHEN b.cond IS NULL THEN 100 ELSE b.b2 END AS b2  
FROM a
LEFT OUTER JOIN (
  SELECT true AS cond, b.*
  FROM b
) AS b
  ON (a.a1 = b.b1);

ใช้การเปรียบเทียบแถว

ง่ายยิ่งขึ้นแม้ว่าจะบังคับค่าเท็จที่เราสามารถเปรียบเทียบได้คือการเปรียบเทียบแถว ใน PostgreSQL แถวจะมีค่าตามชื่อของตาราง ยกตัวอย่างเช่นSELECT foo FROM fooผลตอบแทนแถวชนิดfoo(ซึ่งเป็นประเภทแถว) fooจากตาราง ที่นี่เราทดสอบเพื่อดูว่า ROW นั้นเป็นโมฆะหรือไม่ นี้จะทำงานตราบใดที่ทุกIS NOT NULLคอลัมน์ และถ้าทุกคอลัมน์IS NULLในตารางของคุณแสดงว่าคุณกำลังหมุนรอบ

SELECT
  a.a1,
  b.b1,  
  CASE WHEN b IS NULL THEN 100 ELSE b.b2 END AS b2  
FROM a
LEFT OUTER JOIN b
  ON (a.a1 = b.b1);

คอลัมน์ที่b1ใช้ในCASEการแก้ปัญหาไม่จำเป็นต้องไม่เป็นโมฆะ การก่อสร้างใช้งานได้ทั้งสองกรณี
ypercubeᵀᴹ

1

ฉันคิดว่า COALESCE มีประโยชน์อย่างมากในกรณีนี้ มันจะคืนค่าที่ไม่ใช่ค่า NULL แรกจากรายการ:

SELECT
 a.a1,
 b.b1,
 COALESCE (b.b2, 100) AS b2
FROM a
LEFT OUTER JOIN b
  ON (a.a1 = b.b1);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.