[FROM x, y] หมายถึงอะไรใน Postgres


12

ฉันเพิ่งเริ่มต้นกับ Postgres อ่านเอกสารนี้ฉันเจอแบบสอบถามนี้:

SELECT title, ts_rank_cd(textsearch, query) AS rank
FROM apod, to_tsquery('neutrino|(dark & matter)') query
WHERE query @@ textsearch
ORDER BY rank DESC
LIMIT 10;

ฉันสามารถเข้าใจทุกอย่างในแบบสอบถามนี้ยกเว้นFROM apod, ...สำหรับการนี้:

สิ่งนี้,หมายความว่าอย่างไร ฉันเคยเข้าร่วม แต่ไม่ได้มีหลายFROMงบคั่นด้วยเครื่องหมายจุลภาค

ฉันค้นหาสุทธิโดยไม่มีประโยชน์ หลังจากดูและคิดแล้วฉันคิดว่ามันประกาศตัวแปรที่เรียกว่าแบบสอบถามเพื่อให้สามารถใช้งานได้หลายครั้ง แต่ถ้านี่เป็นเรื่องจริงมันเกี่ยวข้องกับFROMอะไร?

คำตอบ:


10

CROSS JOINมันจะสร้างนัย มันเป็นไวยากรณ์ของ SQL-89

ที่นี่ฉันใช้values(1)และvalues(2)สร้างตาราง pseduo (ตารางค่า) เพื่อเป็นตัวอย่างเท่านั้น สิ่งที่อยู่หลังพวกเขาt(x)และg(y)ถูกเรียกว่าFROM-Aliasesตัวละครที่อยู่ในวงเล็บคือ alias สำหรับคอลัมน์ ( xและyตามลำดับ) คุณสามารถสร้างตารางเพื่อทดสอบสิ่งนี้ได้อย่างง่ายดาย

SELECT *
FROM (values(1)) AS t(x), (values(2)) AS g(y)

นี่คือวิธีที่คุณจะเขียนตอนนี้

SELECT *
FROM (values(1)) AS t(x)
CROSS JOIN (values(2)) AS g(y);

จากที่นั่นคุณสามารถทำให้สิ่งนี้เป็นนัยINNER JOINโดยการเพิ่มเงื่อนไข

SELECT *
FROM (values(1)) AS t(x)
CROSS JOIN (values(1)) AS g(z)
WHERE x = z;

หรือINNER JOINไวยากรณ์ที่ชัดเจนและใหม่กว่า

SELECT *
FROM (values(1)) AS t(x)
INNER JOIN (values(1)) AS g(z)
  ON ( x = z );

ดังนั้นในตัวอย่างของคุณ ..

FROM apod, to_tsquery('neutrino|(dark & matter)') query

นี่เป็นหลักเหมือนกับไวยากรณ์ที่ใหม่กว่า

FROM apod
CROSS JOIN to_tsquery('neutrino|(dark & matter)') AS query

ซึ่งจริงๆแล้วเหมือนกันในกรณีนี้เนื่องจากto_tsquery()ส่งคืนแถวและไม่ใช่ชุดเป็น

SELECT title, ts_rank_cd(
  textsearch,
  to_tsquery('neutrino|(dark & matter)')
) AS rank
FROM apod
WHERE to_tsquery('neutrino|(dark & matter)') @@ textsearch
ORDER BY rank DESC
LIMIT 10;

อย่างไรก็ตามข้างต้นอาจทำให้to_tsquery('neutrino|(dark & matter)')เกิดขึ้นสองครั้ง แต่ในกรณีนี้มันไม่ได้ - to_tsqueryถูกทำเครื่องหมายเป็นเสถียร (ตรวจสอบด้วย\dfS+ to_tsquery)

STABLEบ่งชี้ว่าฟังก์ชั่นไม่สามารถแก้ไขฐานข้อมูลและภายในการสแกนตารางเดียวมันจะส่งคืนผลลัพธ์เดียวกันสำหรับค่าอาร์กิวเมนต์เดียวกัน แต่ผลลัพธ์นั้นสามารถเปลี่ยนแปลงได้ตลอดทั้งคำสั่ง SQL นี่คือการเลือกที่เหมาะสมสำหรับฟังก์ชั่นที่ผลลัพธ์ขึ้นอยู่กับการค้นหาฐานข้อมูลตัวแปรพารามิเตอร์ (เช่นเขตเวลาปัจจุบัน) ฯลฯ (มันไม่เหมาะสมสำหรับทริกเกอร์ AFTER ที่ต้องการแถวการสืบค้นที่แก้ไขโดยคำสั่งปัจจุบัน) โปรดทราบว่า ฟังก์ชั่นตระกูล current_timestamp มีคุณสมบัติว่าเสถียรเนื่องจากค่าของมันไม่เปลี่ยนแปลงภายในการทำธุรกรรม

สำหรับการเปรียบเทียบความแตกต่างระหว่าง SQL-89 และ SQL-92 ที่สมบูรณ์ยิ่งขึ้นดูคำตอบของฉันที่นี่


ขอบคุณมาก. ฉันเพิ่งเริ่มต้นด้วย SQL มันสมเหตุสมผลสำหรับการ,เข้าร่วม cross เนื่องจากเป็นเพียงผลิตภัณฑ์ Cartesian และไม่มีการเปรียบเทียบที่เกี่ยวข้อง คุณสามารถตอบคำถามอีก 1 ข้อได้ไหม มีอะไรt(x)ใน(values(1)) AS t(x)???
andrerpena

@andrerpena อัปเดตแล้ว
Evan Carroll

1
คุณดีที่สุด คำอธิบายที่ชัดเจน ขอบคุณมาก
andrerpena

ไม่เคยได้ยินคำว่า "จากนามแฝง" สำหรับนามแฝงตาราง to_tsquery()ส่งกลับค่าไม่ได้เป็นแถว และเนื่องจากฟังก์ชั่นถูกกำหนดSTABLEนั่นไม่ได้หมายความว่าผู้วางแผนคิวรี่จะหลีกเลี่ยงการประเมินซ้ำ มันสามารถ
Erwin Brandstetter

12

คู่มือมีคำอธิบายโดยละเอียดสำหรับเครื่องหมายจุลภาคในFROMรายการในบทTable Expressions :

ส่วนFROMคำสั่งได้รับตารางจากหนึ่งตารางขึ้นไปที่กำหนดในรายการอ้างอิงตารางที่คั่นด้วยเครื่องหมายจุลภาค

FROM table_reference [, table_reference [, ...]]

การอ้างอิงตารางสามารถเป็นชื่อตาราง (อาจเป็นสคีมาที่ผ่านการรับรอง) หรือตารางที่ได้รับเช่นแบบสอบถามย่อยการJOINสร้างหรือการรวมที่ซับซ้อนของสิ่งเหล่านี้ หากมีการแสดงมากกว่าหนึ่งการอ้างอิงตารางในFROMข้อตารางจะถูกข้ามแบบร่วม (นั่นคือผลิตภัณฑ์คาร์ทีเซียนของแถวของพวกเขาจะเกิดขึ้น; ดูด้านล่าง)

ความจริงที่ว่าการอ้างอิงตารางที่คั่นด้วยเครื่องหมายจุลภาคนั้นถูกกำหนดไว้ในมาตรฐาน SQL รุ่นก่อนหน้ากว่าJOINไวยากรณ์ที่ชัดเจนไม่ได้ทำให้เครื่องหมายจุลภาคไม่ถูกต้องหรือล้าสมัย ใช้ไวยากรณ์การเข้าร่วมอย่างชัดเจนโดยที่จำเป็นทางเทคนิค (ดูด้านล่าง) หรือที่ทำให้ข้อความค้นหาชัดเจนขึ้น

คู่มืออีกครั้ง:

FROM T1 CROSS JOIN T2เทียบเท่ากับFROM T1 INNER JOIN T2 ON TRUE (ดูด้านล่าง) FROM T1, T2นอกจากนี้ยังเป็นเทียบเท่ากับ

แต่ "เทียบเท่า" ไม่ได้หมายความว่าเหมือนกัน มีความแตกต่างเล็กน้อยตามบันทึกคู่มือ :

หมายเหตุความ
เท่าเทียมกันหลังนี้ไม่ได้เก็บไว้อย่างแน่นอนเมื่อมีมากกว่าสองตารางปรากฏขึ้นเนื่องจากJOINผูกให้แน่นมากกว่าเครื่องหมายจุลภาค ตัวอย่างเช่น FROM T1 CROSS JOIN T2 INNER JOIN T3 ON conditionไม่เหมือนกับ FROM T1, T2 INNER JOIN T3 ON conditionเพราะconditionสามารถอ้างอิงT1ในกรณีแรก แต่ไม่ใช่ที่สอง

คำถามที่เกี่ยวข้องนี้แสดงให้เห็นถึงความเกี่ยวข้องของความแตกต่าง:

โดยทั่วไปการสังเกตของคุณถูกต้อง:

ดูเหมือนว่าฉันจะประกาศตัวแปรที่เรียกว่าแบบสอบถามเพื่อให้สามารถใช้งานได้หลายครั้ง

ฟังก์ชันใด ๆ สามารถใช้เป็น "ฟังก์ชันตาราง" ในFROMรายการ และพารามิเตอร์ฟังก์ชันสามารถอ้างอิงคอลัมน์จากตารางทั้งหมดไปทางซ้ายของฟังก์ชันได้เนื่องจากสัญกรณ์:

FROM apod, to_tsquery('neutrino|(dark & matter)') query

เทียบเท่ากับ:

FROM apod CROSS JOIN LATERAL to_tsquery('neutrino|(dark & matter)') AS query

คู่มือการค้นหา LATERAL:

ฟังก์ชั่นที่ปรากฏในตารางFROMนอกจากนี้ยังสามารถนำหน้าด้วยคำที่สำคัญ LATERALแต่สำหรับฟังก์ชั่นคำที่สำคัญเป็นตัวเลือก ; อาร์กิวเมนต์ของฟังก์ชั่นสามารถมีการอ้างอิงไปยังคอลัมน์ที่จัดทำโดยนำหน้ารายการ FROM ในทุกกรณี

เหมืองเน้นหนัก

คำหลักASเป็นสมบูรณ์เสียงตัวเลือกก่อนนามแฝงตาราง (เมื่อเทียบกับนามแฝงคอลัมน์ที่เป็นไม่แนะนำให้งดASเพื่อหลีกเลี่ยงความงงงวยเป็นไปได้) คำตอบที่เกี่ยวข้องมีมากขึ้น:

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.