เคียวรีย่อยเพิ่มพลังการแสดงออกให้กับเคียวรี SQL หรือไม่?


29

SQL ต้องการเคียวรีย่อยหรือไม่?

ลองนึกภาพการนำภาษาคิวรีที่มีโครงสร้างมาใช้อย่างพอเพียงสำหรับฐานข้อมูลที่เกี่ยวข้อง เนื่องจากโครงสร้างของSELECTคำสั่งcanonical SQL นั้นค่อนข้างสำคัญสำหรับเรื่องนี้ฉันจึงไม่สนใจโดยตรงกับพีชคณิตเชิงสัมพันธ์ แต่คุณสามารถใส่กรอบนี้ในเทอมเหล่านั้นโดยกำหนดข้อ จำกัด ที่เหมาะสมในรูปแบบของนิพจน์

SQL แบบSELECTแบบสอบถามโดยทั่วไปประกอบด้วยการฉาย (คนSELECTส่วน) จำนวนบางส่วนของJOINการดำเนินงาน (คนJOINส่วน) จำนวนของSELECTION การดำเนินงาน (ใน SQL ที่WHEREคำสั่ง) และจากนั้นตั้งฉลาดการดำเนินงาน ( UNION, EXCEPT, INTERSECTฯลฯ ) ตามมาด้วยอีกSELECTแบบสอบถามSQL

ตารางที่เข้าร่วมสามารถเป็นผลลัพธ์ของนิพจน์ที่คำนวณได้ กล่าวอีกนัยหนึ่งเราสามารถมีคำสั่งเช่น:

SELECT t1.name, t2.address
  FROM table1 AS t1 
  JOIN (SELECT id, address 
          FROM table2 AS t3 
         WHERE t3.id = t1.id) AS t2
 WHERE t1.salary > 50,000;

เราจะอ้างถึงการใช้ตารางที่คำนวณเป็นส่วนหนึ่งของแบบสอบถาม SQL เป็นแบบสอบถามย่อย ในตัวอย่างข้างต้นที่สอง (เยื้อง) SELECTเป็นแบบสอบถามย่อย

แบบสอบถาม SQL ทั้งหมดสามารถเขียนในลักษณะที่จะไม่ใช้แบบสอบถามย่อยหรือไม่? ตัวอย่างข้างต้นสามารถ:

SELECT t1.name, t2.address
  FROM table1 AS t1 
  JOIN table2 AS t2
    ON t1.id = t2.id
 WHERE t1.salary > 50,000;

ตัวอย่างนี้เป็นของปลอมหรือไม่สำคัญ แต่ก็สามารถจินตนาการได้ว่ามีกรณีที่ต้องใช้ความพยายามมากขึ้นในการกู้คืนนิพจน์ที่เทียบเท่า กล่าวอีกนัยหนึ่งคือทุกกรณีของแบบสอบถาม SQL ที่มีรีย่อยมีไม่มีใด ๆ ที่รับประกันและเพื่อสร้างผลลัพธ์เดียวกันสำหรับตารางต้นแบบเดียวกันหรือไม่ ให้เรา จำกัด แบบสอบถาม SQL ไปยังแบบฟอร์มต่อไปนี้:qqqq

SELECT <attribute>,
      ...,
      <attribute>
 FROM <a table, not a subquery>
 JOIN <a table, not a subquery>
  ...
 JOIN <a table, not a subquery>
WHERE <condition>
  AND <condition>
  ...
  AND <condition>

UNION
 -or-
EXCEPT
 -or-
<similar>

SELECT ...

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


5
ลำไส้ของฉันบอกฉันว่าคุณสามารถเข้าร่วมทุกอย่างด้วยกันและเลือกจากที่นั่นตราบใดที่คุณไม่ต้องการค่าที่สรุปรวม การเลือกรายการทั้งหมดที่มีค่ามากกว่าค่าเฉลี่ยของคอลัมน์จะต้องคำนวณค่าเฉลี่ยก่อนดังนั้นจึงต้องมีแบบสอบถามย่อย
กราฟิลส์

@ ราฟาเอลฉันค่อนข้างแน่ใจว่าคุณสามารถทำได้แม้กระทั่งค่ารวมคุณเพียงแค่ต้องทำการรวมตัวเองและกลุ่มละมากขึ้น (ทำให้มีขนาดใหญ่ขึ้นอย่างมาก ไม่แน่ใจว่าฉันจะพิสูจน์อย่างเป็นทางการว่าคุณสามารถทำทุกอย่างได้
Kevin

@Kevin คุณแน่ใจหรือไม่ว่าจำนวนการปฏิบัติการที่จำเป็นไม่ได้ขึ้นอยู่กับจำนวนแถว เพราะเราไม่มีสิ่งนั้นเราทำได้ไหม
กราฟิลส์

1
select count(*) from (select id from sometable group by id having count(*)>1) dตัวอย่างปกติฉันมีกำหนดแบบสอบถามย่อยเป็นรายการที่ซ้ำกันนับ: เพราะมันรวมถึงgroup byฉันยังไม่ได้ใส่คำตอบนี้
Mark Hurd

BTW AFAIK ใน SQL ปกติONจำเป็นต้องใช้ clause สำหรับJOINs แม้ว่าจะได้รับผลิตภัณฑ์ข้ามโดยใช้เครื่องหมายจุลภาค
Mark Hurd

คำตอบ:


9

มีบางคำศัพท์ที่สับสน บล็อกแบบสอบถามภายในวงเล็บ

SELECT t1.name, t2.address
  FROM table1 
  JOIN (SELECT id, address 
          FROM table2 AS t3 
         WHERE t3.id = t1.id) 

เรียกว่ามุมมองภายใน แบบสอบถามย่อยเป็นบล็อกแบบสอบถามภายในทั้ง WHERE หรือข้อเลือกเช่น

select deptno from dept
where 3 < (select count(1) from emp 
           where dept.deptno=emp.deptno)

ไม่ว่าในกรณีใดมุมมองภายในหรือแบบสอบถามย่อยสามารถไม่ถูกทำให้สับสนในโครงการแบบ "แบน" จำกัด - เข้าร่วม เคียวรีย่อยที่สัมพันธ์กันซึ่งมีการรวมการ Unests เข้าไปในมุมมองภายในด้วยการจัดกลุ่มซึ่งจะทำการ Unests เข้าไปในเคียวรีแบบแบน

select deptno from dept d
    where 3 < (select avg(sal) from emp e
               where d.deptno=e.deptno)

select d.deptno from dept d, ( 
    select deptno from emp e
    group by deptno
    having avg(sal) > 3
) where d.deptno=e.deptno

select d.deptno from dept d, emp e
where d.deptno=e.deptno 
group by d.deptno
having avg(sal) > 3

ในฐานะที่เป็นกฎระเบียบที่เกี่ยวกับพีชคณิตสำหรับการเพิ่มประสิทธิภาพแบบสอบถามเชิงพีชคณิตเป็นที่รู้จักกันที่จะเข้าไปใน axiomatized สัมพันธ์ Latticeที่ง่ายแปลงแบบสอบถามที่แสดงให้เห็นที่นี่และมี


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

16

หากต้องการแปลข้อความของคุณเป็นพีชคณิตเชิงสัมพันธ์ฉันคิดว่ามันถามว่า:

เราสามารถเขียนเป็นไหม?σA(A)σB(B)σA(σB(AB))

(ที่ถูกเลือกและกำลังเข้าร่วม)σ

คำตอบคือ "ใช่" และเป็นการเพิ่มประสิทธิภาพการค้นหามาตรฐาน พูดตามตรงฉันไม่แน่ใจว่าจะพิสูจน์ได้อย่างไรในลักษณะที่ไม่มีการขอทาน - มันเป็นเพียงแค่คุณสมบัติของการคัดเลือกและเข้าร่วม คุณสามารถโต้แย้ง inductively เพื่อเพิ่มหลายชั้นซ้อนของแบบสอบถามที่คุณต้องการ

นอกจากนี้คุณอาจถาม:

ลำดับการรวมทั้งหมดสามารถเขียนเป็น [เมื่อเทียบกับพูด ]?ABC(AB)(CD)

คำตอบคือใช่อีกครั้งเพราะการเข้าร่วมนั้นเชื่อมโยงกัน งบที่คล้ายกันสามารถทำเกี่ยวกับการฉายเช่นกัน

ประเภทของ "subquery" ที่น่าสังเกตชนิดหนึ่งซึ่งฉันคิดว่าไม่สามารถ "แบนออก" withได้ วิธีหนึ่งในการดูสิ่งนี้คือการสังเกตว่าถ้าคุณมีwithคำสั่งแล้วคุณสามารถมีฟังก์ชันแบบเรียกซ้ำซึ่งไม่สามารถเขียนได้โดยไม่ต้องใช้แบบสอบถามย่อย

ดังนั้นเพื่อสรุป: ในกรณีเฉพาะที่คุณพูดถึงไม่ SQL ไม่ต้องการเคียวรีย่อยและคุณสามารถพิสูจน์ inductively โดยทั่วไปแล้วมีคุณสมบัติที่ต้องใช้แบบสอบถามย่อย


พฤติกรรมแบบเรียกซ้ำผ่านทางwithได้รับการแนะนำใน SQL: 1999 และทำให้ภาษาที่แสดงออกมีความหมายชัดเจน
András Salamon

1

"เคียวรีย่อยเพิ่มพลังการแสดงออกให้กับเคียวรี SQL หรือไม่"

พวกเขาทำอย่างน้อยก่อนที่จะมีการแนะนำ EXCEPT ในภาษา SQL

ก่อนที่จะมีการยกเว้น EXCEPT ไม่มีวิธีใดที่จะแสดงความแตกต่างเชิงสัมพันธ์หรือ semidifference ใน SQL โดยไม่ต้องหันไปใช้เคียวรีย่อย

วันนี้ผู้ประกอบการดั้งเดิม "ทั่วไป" ของพีชคณิตเชิงสัมพันธ์ทั้งหมดสามารถแสดงได้โดยไม่ต้องมีแบบสอบถามย่อย:

เข้าร่วมธรรมชาติสามารถทำได้โดยผ่านธรรมชาติเข้าร่วมหรือเข้าร่วมกับ
ยูเนี่ยนสามารถทำได้ผ่านยูเนี่ยน
ลบสามารถทำได้ผ่าน
โครงการยกเว้น/ RENAME / ขยายสามารถทำได้ผ่านข้อ
จำกัดเลือกสามารถทำได้ผ่านที่สัมพัทธ์
เชิงสัมพันธ์สามารถทำได้ผ่านค่า
ปิดสัมพัทธ์ จะทำผ่านซ้ำด้วย

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