แบบสอบถามที่ซ้อนกันใน SQL

ภาษา SQL ช่วยให้คุณสามารถซ้อนหนึ่งแบบสอบถามภายในแบบสอบถามอื่น สิ่งนี้ทำให้สามารถเขียนเคียวรีขนาดใหญ่มากหนึ่งรายการที่จะทำบางสิ่งที่ใหญ่และซับซ้อนได้ แม้ว่าความสามารถในการอ่านโค้ดจะลดลงอย่างมากก็ตาม

พื้นที่ที่สามารถใช้การเปลี่ยนแปลงขึ้นอยู่กับจำนวนค่าที่ส่งคืนโดยแบบสอบถามย่อย มีทั้งหมดสามตัวเลือก:

  • แบบสอบถามย่อยส่งกลับหนึ่งค่าเดียว (หนึ่งคอลัมน์และหนึ่งแถว)
  • แบบสอบถามย่อยส่งคืนรายการค่า (ตารางที่มีหนึ่งคอลัมน์)
  • ข้อความค้นหาย่อยส่งคืนตาราง (หลายคอลัมน์ จำนวนแถวเท่าใดก็ได้)

ลองดูตัวอย่างสำหรับแต่ละกรณี

แบบสอบถามย่อยที่มีผลสเกลาร์

มาดูรายชื่อพนักงานทั้งหมดของเราจากตารางพนักงานที่มีเงินเดือนสูงกว่าค่าเฉลี่ยของบริษัทกัน เราจะทำได้อย่างไร?

เราสามารถกรองพนักงานได้อย่างง่ายดายโดยการเปรียบเทียบเงินเดือนกับค่าเฉลี่ยหากเราทราบล่วงหน้า ในเวลาเดียวกันเราได้เขียนแบบสอบถามที่ช่วยให้เราสามารถคำนวณเงินเดือนเฉลี่ยของพนักงานของ บริษัท ได้ จำไว้:

SELECT AVG(salary) FROM employee 

จากนั้น MySQL คืนค่าให้เรา: 76833.3333

จะหารายชื่อพนักงานทุกคนที่เงินเดือนสูงกว่าค่าเฉลี่ยได้อย่างไร นอกจากนี้ยังง่ายมาก:

 SELECT * FROM employee 
   WHERE salary > 76833.3333 

ผลลัพธ์ของแบบสอบถามนี้จะเป็น:

รหัส ชื่อ อาชีพ เงินเดือน
1 อีวานอฟ อีวาน โปรแกรมเมอร์ 100,000
2 เปตรอฟ เปตรอฟ โปรแกรมเมอร์ 80000
4 ราบิโนวิช มอยชา ผู้อำนวยการ 200,000

และตอนนี้เราเพิ่งรวมคำขอทั้งสองโดยแทนที่คำขอแรกแทนค่า 76833:

   SELECT * FROM employee 
   WHERE salary > (SELECT AVG(salary) FROM employee) 

ผลลัพธ์ของแบบสอบถามนี้จะเหมือนกัน:

รหัส ชื่อ อาชีพ เงินเดือน
1 อีวานอฟ อีวาน โปรแกรมเมอร์ 100,000
2 เปตรอฟ เปตรอฟ โปรแกรมเมอร์ 80000
4 ราบิโนวิช มอยชา ผู้อำนวยการ 200,000

แบบสอบถามย่อยพร้อมรายการค่า

คุณจำได้ไหมว่าครั้งหนึ่งเราเคยทำงาน - เพื่อค้นหาบันทึกทั้งหมดจากตารางหนึ่งซึ่งไม่มีบันทึกที่สอดคล้องกันจากอีกตารางหนึ่ง

มีภาพนี้ด้วย:

ถ้าจำไม่ผิด งานจะเป็นดังนี้: แสดง ราย ชื่อพนักงานทั้งหมดจากตารางพนักงานที่ไม่มีงานในตารางงาน

เรามาหาทางออกในสองขั้นตอนกัน

ขั้นแรก ให้เขียนแบบสอบถามที่จะส่งคืนรหัสของพนักงานทุกคนที่มีงานในตารางงาน เพียงจำสองสิ่ง:

  • ลบรายการที่ซ้ำกัน - ใช้คำหลัก DISTINCT
  • ลบค่า NULL ออกจากผลลัพธ์
SELECT DISTINCT employee_id FROM task 
   WHERE employee_id IS NOT NULL

และที่นี่เราได้ผลลัพธ์ที่สวยงามจากคำขอดังกล่าว:

รหัสพนักงาน
1
2
5
4
6

ขอจดชั่วคราวเพื่อความสะดวกตามลำดับ: 1,2,5,4,6 ตอนนี้มาเขียนแบบสอบถามที่สอง - ไปที่ตารางพนักงานซึ่งจะส่งคืนรายชื่อพนักงานที่ไม่มีรหัสอยู่ในรายการแรก:

SELECT * FROM employee  
WHERE id NOT IN (1,2,5,4,6)

และผลลัพธ์ของแบบสอบถามนี้:

รหัส ชื่อ อาชีพ เงินเดือน อายุ เข้าร่วม_วันที่
3 อีวานอฟ เซอร์เกย์ เทสเตอร์ 40000 สามสิบ 2014-01-01

และในตอนนี้ เช่นเดียวกับในตัวอย่างก่อนหน้านี้ คุณสามารถรวมคำขอทั้งสองได้โดยเพียงแค่แทนที่เนื้อหาของคำขอแรกแทนรายการ id

 SELECT * FROM employee 
   WHERE id NOT IN ( 
      	SELECT DISTINCT employee_id FROM task 
      	WHERE employee_id IS NOT NULL 
   )