คล้ายกับแบบสอบถามย่อยที่มีความสัมพันธ์มากกว่า
การLATERAL
เข้าร่วม (Postgres 9.3 หรือใหม่กว่า) เป็นเหมือนแบบสอบถามย่อยที่มีความสัมพันธ์ไม่ใช่แบบสอบถามย่อยธรรมดา เช่นเดียวกับAndomar ชี้ให้เห็น , ฟังก์ชั่นหรือแบบสอบถามย่อยไปทางขวาของที่LATERAL
เข้าร่วมจะต้องมีการประเมินผลครั้งเดียวสำหรับแต่ละแถวด้านซ้ายของมัน - เช่นเดียวกับความสัมพันธ์แบบสอบถามย่อย - ในขณะที่แบบสอบถามย่อยธรรมดา (การแสดงออกของตาราง) คือการประเมินครั้งเดียวเท่านั้น (ผู้วางแผนคิวรีมีวิธีเพิ่มประสิทธิภาพสำหรับทั้งสองอย่าง)
คำตอบที่เกี่ยวข้องนี้มีตัวอย่างโค้ดสำหรับทั้งสองด้านเคียงข้างกันเพื่อแก้ปัญหาเดียวกัน:
สำหรับการส่งคืนมากกว่าหนึ่งคอลัมน์LATERAL
โดยทั่วไปการเข้าร่วมจะง่ายกว่าสะอาดกว่าและเร็วกว่า
นอกจากนี้โปรดจำไว้ว่าสิ่งที่เทียบเท่าของแบบสอบถามย่อยที่มีความสัมพันธ์คือLEFT JOIN LATERAL ... ON true
:
อ่านคู่มือการใช้งาน LATERAL
มันมีอำนาจมากกว่าสิ่งใดที่เราจะตอบคำถามที่นี่:
สิ่งที่แบบสอบถามย่อยไม่สามารถทำได้
มีเป็นสิ่งที่LATERAL
เข้าร่วมสามารถทำได้ แต่ (ความสัมพันธ์) แบบสอบถามย่อยไม่สามารถ (ง่าย) เคียวรีย่อยที่สัมพันธ์กันสามารถส่งคืนค่าเดียวไม่ใช่หลายคอลัมน์และไม่ใช่หลายแถว - ยกเว้นการเรียกใช้ฟังก์ชันเปล่า (ซึ่งคูณผลลัพธ์แถวหากพวกเขาส่งคืนแถวจำนวนมาก) แต่แม้แต่ฟังก์ชั่นการคืนค่าบางอย่างก็สามารถทำได้ในFROM
ข้อ เช่นเดียวunnest()
กับหลายพารามิเตอร์ใน Postgres 9.4 หรือใหม่กว่า คู่มือ:
อนุญาตเฉพาะในFROM
ข้อ;
ดังนั้นจึงใช้งานได้ แต่ไม่สามารถแทนที่ด้วยแบบสอบถามย่อยได้อย่างง่ายดาย:
CREATE TABLE tbl (a1 int[], a2 int[]);
SELECT * FROM tbl, unnest(a1, a2) u(elem1, elem2); -- implicit LATERAL
เครื่องหมายจุลภาค ( ,
) ในประโยคเป็นโน้ตสั้นFROM
ๆ ถูกสันนิษฐานโดยอัตโนมัติสำหรับฟังก์ชันตาราง
เพิ่มเติมเกี่ยวกับกรณีพิเศษของ:CROSS JOIN
LATERAL
UNNEST( array_expression [, ... ] )
ฟังก์ชั่น Set-return ในSELECT
รายการ
นอกจากนี้คุณยังสามารถใช้ฟังก์ชั่นตั้งคืนเช่นเดียวกับunnest()
ในSELECT
รายการโดยตรง สิ่งนี้เคยแสดงพฤติกรรมที่น่าประหลาดใจกับฟังก์ชันดังกล่าวมากกว่าหนึ่งSELECT
รายการในรายการเดียวกันจนถึง Postgres 9.6 แต่ในที่สุดมันก็ถูกทำให้สะอาดด้วย Postgres 10และเป็นทางเลือกที่ถูกต้องในตอนนี้ (แม้ว่าจะไม่ใช่ SQL มาตรฐาน) ดู:
ตัวอย่างอาคารด้านบน:
SELECT *, unnest(a1) AS elem1, unnest(a2) AS elem2
FROM tbl;
เปรียบเทียบ:
dbfiddle สำหรับ pg 9.6 ที่นี่
dbfiddle สำหรับ pg 10 ที่นี่
ชี้แจงข้อมูลที่ผิด
คู่มือ:
สำหรับประเภทINNER
และOUTER
ประเภทการเข้าร่วมจะต้องระบุเงื่อนไขการเข้าร่วมนั่นคือหนึ่งในประเภททั้งหมดNATURAL
, ON
join_conditionหรือUSING
( join_column [, ... ]) ดูความหมายด้านล่าง
สำหรับCROSS JOIN
คำสั่งเหล่านี้ไม่สามารถปรากฏได้
ดังนั้นข้อความค้นหาทั้งสองนี้จึงถูกต้อง (แม้ว่าจะไม่มีประโยชน์อย่างยิ่ง):
SELECT *
FROM tbl t
LEFT JOIN LATERAL (SELECT * FROM b WHERE b.t_id = t.t_id) t ON TRUE;
SELECT *
FROM tbl t, LATERAL (SELECT * FROM b WHERE b.t_id = t.t_id) t;
ในขณะที่คนนี้ไม่ได้:
SELECT *
FROM tbl t
LEFT JOIN LATERAL (SELECT * FROM b WHERE b.t_id = t.t_id) t;
นั่นเป็นสาเหตุที่ตัวอย่างรหัสของ @ Andomarนั้นถูกต้อง ( CROSS JOIN
ไม่ต้องการเงื่อนไขการเข้าร่วม) และ@ Attila นั้นไม่ถูกต้อง
apply
เป็นเช่นเดียวกับlateral
มาตรฐานของ SQL)