มันคืออะไร เหตุใดจึงมีความสำคัญ และใช้งานอย่างไร
Common Table Expression (CTE) หรือที่เรียกว่า "แบบสอบถามด้วย" ใช้เพื่อแยกย่อยแบบสอบถามที่ซับซ้อนออกเป็นส่วนที่เรียบง่ายและจัดการได้มากขึ้น ช่วยเพิ่มความสามารถในการอ่านโค้ด SQL มันมีประโยชน์มากเมื่อเขียนแบบสอบถามที่มีแบบสอบถามย่อยที่ซับซ้อน โดยจะตั้งชื่อชั่วคราวให้กับแบบสอบถามย่อยที่ซับซ้อนก่อนที่จะใช้ในแบบสอบถามที่ใหญ่กว่า
CTE มีสองประเภท: ปกติและแบบเรียกซ้ำ (CTE แบบเรียกซ้ำไม่ครอบคลุมในบริบทนี้)
การสร้างนิพจน์ตารางทั่วไป
แบบสอบถาม CTE ถูกเขียนโดยใช้ไวยากรณ์ต่อไปนี้:
WITH cte_name (column_name) AS (query) SELECT * FROM CTE_NAME;
พิจารณาตารางที่เรียกว่า `บุคคล`;
| id | first_name | last_name | email | gender | country_of_birth | car_make | |----|--------------|-------------|-----------------------------|--------|------------------|-------------| | 1 | Vikki | Balsillie | [email protected] | Female | Indonesia | Nissan | | 2 | Lorettalorna | Fetteplace | [email protected] | Female | United Kingdom | Plymouth | | 3 | Ileana | Guerin | [email protected] | Female | Bulgaria | null | | 4 | Walden | Milmo | null | Male | Russia | Ford | | 5 | Quincy | Bromont | null | Male | China | Lexus | | 6 | Maria | Iddon | [email protected] | Female | Philippines | Land Rover | | 7 | Rog | McArdell | [email protected] | Male | Poland | null |
ซอร์สโค้ด รวมถึงการสืบค้นสำหรับการสร้างตารางนี้ สามารถพบได้บน GitHub
เราต้องการค้นหาผู้ที่มีที่อยู่อีเมล เราสามารถใช้ CTE เพื่อทำสิ่งนี้ได้ดังนี้:
-- Create A CTE named 'got_email' to select rows where the email is non-null -- and select specific columns from the 'got_email' cte WITH got_email AS (SELECT * FROM person WHERE email IS NOT NULL) SELECT id,first_name,last_name FROM got_email;
บรรทัดแรกของ CTE กำหนด CTE ที่เรียกว่า `got_email` CTE จะเลือกแถวทั้งหมดจากตาราง `person` โดยที่คอลัมน์ `email` ไม่ใช่ค่าว่าง
บรรทัดที่สองของการสืบค้นจะเลือกชุดย่อยของคอลัมน์จาก CTE `got_email`
แบบสอบถามนี้จะส่งกลับผลลัพธ์ต่อไปนี้:
| id | first_name | last_name | |----|--------------|-------------| | 1 | Vikki | Balsillie | | 2 | Lorettalorna | Fetteplace | | 3 | Ileana | Guerin | | 6 | Maria | Iddon | | 7 | Rog | McArdell |
มีคำหลักบางคำที่ไม่สามารถนำมาใช้โดยตรงภายใน CTE ได้ คำสำคัญเช่น INSERT, UPDATE, DELETE, GROUP BY, HAVING, ORDER BY, LIMIT, OFFSET CTE ส่วนใหญ่จะใช้ในการสืบค้นและเลือกข้อมูล
นิพจน์ตารางทั่วไปหลายรายการ
สามารถสร้างนิพจน์ตารางทั่วไปหลายรายการได้โดยใช้ไวยากรณ์ด้านล่าง
WITH cte_name1 (column_name) AS (query), cte_name2 (column_name) AS (query) SELECT * FROM cte_name1 UNION ALL SELECT * FROM cte_name2;
CTE แรกถูกแยกออกจาก CTE ที่สองด้วยตัวดำเนินการลูกน้ำ จากนั้นรวมเข้ากับคำสั่ง SELECT นอกคำจำกัดความของ CTE
CTE หลายตัวสามารถใช้สำหรับการดำเนินการ UNION, UNION ALL, JOIN, INTERSECT หรือ EXCEPT
เราจะใช้ตารางเดียวกันด้านบนเพื่ออธิบาย CTE หลายรายการ ในตาราง มีเรกคอร์ดอยู่สองประเภท(บุคคล) ผู้ที่มีทั้งที่อยู่อีเมลและรถยนต์ ผู้ที่มีทั้งที่อยู่อีเมลหรือรถยนต์
| id | first_name | last_name | email | gender | country_of_birth | car_make | |----|--------------|-------------|-----------------------------|--------|------------------|-------------| | 1 | Vikki | Balsillie | [email protected] | Female | Indonesia | Nissan | | 2 | Lorettalorna | Fetteplace | [email protected] | Female | United Kingdom | Plymouth | | 3 | Ileana | Guerin | [email protected] | Female | Bulgaria | null | | 4 | Walden | Milmo | null | Male | Russia | Ford | | 5 | Quincy | Bromont | null | Male | China | Lexus | | 6 | Maria | Iddon | [email protected] | Female | Philippines | Land Rover | | 7 | Rog | McArdell | [email protected] | Male | Poland | null |
คราวนี้ เราต้องการกรองตารางเพื่อแสดงเฉพาะบันทึกที่บุคคลนั้นมีทั้งที่อยู่อีเมลและรถยนต์
เราสามารถทำได้โดยใช้ CTE หลายรายการ:
--Create two CTEs named 'no_email' and 'no_car' -- filter rows from the 'person' table except those in 'no_email' and 'no_car' CTEs WITH no_email AS (SELECT * FROM person WHERE email IS NULL), no_car AS (SELECT * FROM person WHERE car_make IS NULL) SELECT * FROM person EXCEPT (SELECT * FROM no_email UNION ALL SELECT * FROM no_car);
บรรทัดแรกกำหนด CTE `no_email` ซึ่งเลือกบันทึกทั้งหมดจากตาราง 'person' โดยที่คอลัมน์ 'email' เป็นค่าว่าง คั่นด้วยตัวดำเนินการลูกน้ำคือ CTE `no_car` ตัวที่สอง ซึ่งจะเลือกบันทึกทั้งหมดจากตาราง `person` โดยที่คอลัมน์ `car_make` เป็นโมฆะ
หลังจากคำจำกัดความของ CTE จะเป็น `SELECT ภายนอก ` ข้อความค้นหาที่กรองแถวจากตาราง `บุคคล` ยกเว้นแถวใน `no_email` และ `no_car` CTEs
ตารางผลลัพธ์;
| id | first_name | last_name | email | gender | country_of_birth | car_make | |----|--------------|-------------|-----------------------------|--------|------------------|-------------| | 1 | Vikki | Balsillie | [email protected] | Female | Indonesia | Nissan | | 2 | Lorettalorna | Fetteplace | [email protected] | Female | United Kingdom | Plymouth | | 6 | Maria | Iddon | [email protected] | Female | Philippines | Land Rover |
การเปรียบเทียบ CTE และตารางชั่วคราว
คุณอาจสงสัยว่า ฟังดูเหมือนโต๊ะชั่วคราว ทำไมไม่ใช้โต๊ะชั่วคราวล่ะ? มีความแตกต่างที่สำคัญบางประการระหว่าง CTE และตารางชั่วคราว
1. CTE ถูกกำหนดโดยใช้ส่วนคำสั่ง `WITH`
ตารางชั่วคราวถูกสร้างขึ้นโดยใช้คำสั่ง `CREATE TEMPORARY TABLE`
2 CTE จะไม่ถูกจัดเก็บเป็นวัตถุทางกายภาพในฐานข้อมูลซึ่งหมายความว่าไม่ได้จัดเก็บไว้บนดิสก์
ตารางชั่วคราวคือตารางทางกายภาพที่มีอยู่ชั่วคราวบนเซิร์ฟเวอร์ฐานข้อมูล มันใช้พื้นที่ดิสก์
3. CTE คือชุดผลลัพธ์ชั่วคราวที่มีอยู่เฉพาะในช่วงระยะเวลาของการสืบค้นเดียวที่อ้างอิงถึงมัน
มีตารางชั่วคราวในช่วงระยะเวลาของเซสชัน
5. CTE ไม่ได้รับประกันประสิทธิภาพรันไทม์ที่ดีขึ้นเสมอไป อย่างไรก็ตาม ช่วยจัดระเบียบการสืบค้นของคุณ
ตารางชั่วคราวสามารถปรับปรุงประสิทธิภาพรันไทม์ได้ โดยเฉพาะอย่างยิ่งเมื่อเราจำเป็นต้องอ้างอิงข้อมูลเดียวกันหลายครั้ง
6. CTE เองก็ไม่สามารถมีดัชนีได้โดยตรง อย่างไรก็ตาม คุณสามารถสร้างดัชนีบนตารางที่ CTE อ้างอิงได้
คุณสามารถสร้างดัชนีบนคอลัมน์ของตารางชั่วคราวได้ เช่นเดียวกับที่คุณสร้างกับตารางทั่วไป
บทสรุป
CTE สามารถทำให้การสืบค้นที่ซับซ้อนอ่านง่ายขึ้นโดยการแบ่งออกเป็นส่วนย่อยๆ ที่มีชื่อ ซึ่งทำให้เข้าใจตรรกะของการสืบค้นได้ง่ายขึ้น นอกจากนี้ยังส่งเสริมการจัดระเบียบรหัสที่ดีขึ้น
CTE มอบโซลูชันที่ไม่เกี่ยวข้องกับการจัดเก็บข้อมูลทางกายภาพบนเซิร์ฟเวอร์ฐานข้อมูล ด้วยการใช้ประโยชน์จาก CTE นักพัฒนาสามารถเขียนโค้ดที่เข้าใจได้ซึ่งสามารถปรับให้เหมาะสมได้ดีขึ้นเมื่อจำเป็น
ขอบคุณที่อ่านจนจบ โปรดพิจารณาติดตามผู้เขียนและสิ่งพิมพ์นี้ ไปที่ Stackademic เพื่อดูข้อมูลเพิ่มเติมว่าเราทำให้การศึกษาด้านการเขียนโปรแกรมฟรีทั่วโลกเป็นประชาธิปไตยได้อย่างไร