Subquery ใน SELECT Clause
ในบทความก่อนหน้า เราได้เรียนรู้เกี่ยวกับการใช้ Subquery ใน WHERE Clause เพื่อกรองข้อมูลที่เราต้องการดึงออกมาจากฐานข้อมูล บทความนี้จะพาคุณไปรู้จักกับการใช้ Subquery อีกรูปแบบหนึ่ง นั่นคือการใช้ Subquery ใน SELECT Clause ซึ่งมีประโยชน์ในการดึงข้อมูลเพิ่มเติมที่เกี่ยวข้องกับแต่ละแถวที่เราเลือก
Subquery ใน SELECT Clause คืออะไร?
Subquery ใน SELECT Clause คือ Subquery ที่ถูกวางไว้ในส่วนของ SELECT statement เพื่อดึงข้อมูลเพิ่มเติมที่เกี่ยวข้องกับแต่ละแถวที่ถูกเลือกจากตารางหลัก โดย Subquery นี้จะถูก execute หนึ่งครั้งสำหรับแต่ละแถวในผลลัพธ์ของ query หลัก
ข้อจำกัดสำคัญ: Subquery ใน SELECT Clause ต้องคืนค่าเพียงค่าเดียว (single value) สำหรับแต่ละแถว หาก Subquery คืนค่ามากกว่าหนึ่งค่า จะเกิดข้อผิดพลาดขึ้น
เหตุผลในการใช้ Subquery ใน SELECT Clause
การใช้ Subquery ใน SELECT Clause มีประโยชน์ในหลายสถานการณ์ เช่น:
- ดึงข้อมูลที่เกี่ยวข้อง: ดึงข้อมูลสรุป หรือข้อมูลที่เกี่ยวข้องกับแต่ละแถวจากตารางอื่น
- คำนวณค่า: คำนวณค่าต่างๆ เช่น ค่าเฉลี่ย, ผลรวม, หรือจำนวนนับ ที่เกี่ยวข้องกับแต่ละแถว
- แสดงข้อมูลแบบสรุป: แสดงข้อมูลสรุป เช่น ชื่อลูกค้าและจำนวนคำสั่งซื้อทั้งหมดของลูกค้ารายนั้น
ตัวอย่างการใช้งาน Subquery ใน SELECT Clause
สมมติว่าเรามีสองตาราง: customers และ orders
CREATE TABLE customers (
customer_id INT PRIMARY KEY,
customer_name VARCHAR(255)
);
CREATE TABLE orders (
order_id INT PRIMARY KEY,
customer_id INT,
order_date DATE,
amount DECIMAL(10, 2),
FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
);
INSERT INTO customers (customer_id, customer_name) VALUES
(1, 'John Doe'),
(2, 'Jane Smith'),
(3, 'Peter Jones');
INSERT INTO orders (order_id, customer_id, order_date, amount) VALUES
(101, 1, '2023-01-15', 100.00),
(102, 1, '2023-02-20', 150.00),
(103, 2, '2023-03-10', 200.00),
(104, 3, '2023-04-05', 50.00),
(105, 3, '2023-05-12', 75.00),
(106, 3, '2023-06-20', 120.00);
เราต้องการดึงข้อมูลลูกค้าแต่ละคน พร้อมกับจำนวนคำสั่งซื้อทั้งหมดของลูกค้าแต่ละคน
SELECT
customer_id,
customer_name,
(SELECT COUNT(*) FROM orders WHERE customer_id = customers.customer_id) AS total_orders
FROM
customers;
คำอธิบาย:
SELECT customer_id, customer_name: เลือกคอลัมน์customer_idและcustomer_nameจากตารางcustomers(SELECT COUNT(*) FROM orders WHERE customer_id = customers.customer_id) AS total_orders: นี่คือ Subquery ที่อยู่ในSELECTClauseSELECT COUNT(*) FROM orders WHERE customer_id = customers.customer_id: Subquery นี้จะนับจำนวนแถวในตารางordersที่มีcustomer_idตรงกับcustomer_idของแถวปัจจุบันในตารางcustomers(สังเกตว่าเราใช้customers.customer_idเพื่ออ้างอิงถึงคอลัมน์customer_idในตารางหลัก)AS total_orders: กำหนด alias ให้กับผลลัพธ์ของ Subquery ว่าtotal_orders
ผลลัพธ์ที่ได้จะเป็นดังนี้:
+-------------+---------------+--------------+
| customer_id | customer_name | total_orders |
+-------------+---------------+--------------+
| 1 | John Doe | 2 |
| 2 | Jane Smith | 1 |
| 3 | Peter Jones | 3 |
+-------------+---------------+--------------+
เราจะเห็นว่าแต่ละแถวในผลลัพธ์ประกอบด้วยข้อมูลลูกค้า (customer_id และ customer_name) และจำนวนคำสั่งซื้อทั้งหมดของลูกค้าคนนั้น (total_orders) ซึ่งถูกดึงมาจาก Subquery
ตัวอย่างเพิ่มเติม: ดึงค่าเฉลี่ยของยอดสั่งซื้อ
เราสามารถใช้ Subquery ใน SELECT Clause เพื่อคำนวณค่าเฉลี่ยของยอดสั่งซื้อของลูกค้าแต่ละคนได้ดังนี้:
SELECT
customer_id,
customer_name,
(SELECT AVG(amount) FROM orders WHERE customer_id = customers.customer_id) AS average_order_amount
FROM
customers;
คำอธิบาย:
(SELECT AVG(amount) FROM orders WHERE customer_id = customers.customer_id) AS average_order_amount: Subquery นี้จะคำนวณค่าเฉลี่ยของคอลัมน์amountในตารางordersโดยกรองเฉพาะแถวที่มีcustomer_idตรงกับcustomer_idของแถวปัจจุบันในตารางcustomers
ข้อควรระวังในการใช้ Subquery ใน SELECT Clause
แม้ว่า Subquery ใน SELECT Clause จะมีประโยชน์ แต่ก็มีข้อควรระวังที่ต้องคำนึงถึง:
- ประสิทธิภาพ: การใช้ Subquery ใน
SELECTClause อาจส่งผลต่อประสิทธิภาพของ query โดยเฉพาะอย่างยิ่งถ้าตารางมีขนาดใหญ่ เนื่องจาก Subquery จะถูก execute หนึ่งครั้งสำหรับแต่ละแถวในตารางหลัก ในกรณีที่ query ช้าเกินไป อาจพิจารณาใช้JOINเพื่อให้ได้ผลลัพธ์ที่คล้ายกัน แต่มีประสิทธิภาพที่ดีกว่า - Single Value Requirement: Subquery ใน
SELECTClause ต้องคืนค่าเพียงค่าเดียว หาก Subquery คืนค่ามากกว่าหนึ่งค่า จะเกิดข้อผิดพลาดขึ้น - ความซับซ้อน: การใช้ Subquery ที่ซับซ้อนมากเกินไป อาจทำให้ query อ่านยากและเข้าใจยาก พยายามเขียน Subquery ให้ง่ายและชัดเจนที่สุดเท่าที่จะทำได้
เหตุผลเชิงออกแบบ: Trade-offs และแนวปฏิบัติที่ดี
การตัดสินใจว่าจะใช้ Subquery ใน SELECT Clause หรือไม่ ควรพิจารณาจาก trade-offs ด้านประสิทธิภาพและความซับซ้อน
- ประสิทธิภาพ vs. ความง่ายในการเขียน: Subquery อาจเขียนง่ายกว่า
JOINในบางสถานการณ์ แต่โดยทั่วไปJOINจะมีประสิทธิภาพดีกว่า โดยเฉพาะอย่างยิ่งเมื่อทำงานกับตารางขนาดใหญ่ หากประสิทธิภาพเป็นสิ่งสำคัญ ให้พิจารณาใช้JOINแทน - ความสามารถในการอ่าน: Subquery ที่ซับซ้อนอาจทำให้อ่าน query ยากขึ้น พยายามเขียน Subquery ให้สั้นและชัดเจน หาก Subquery ซับซ้อนมากเกินไป อาจพิจารณาแบ่ง query ออกเป็นหลายขั้นตอน หรือใช้ View เพื่อลดความซับซ้อน
แนวปฏิบัติที่ดี:
- ใช้ alias: กำหนด alias ให้กับ Subquery เพื่อให้ query อ่านง่ายขึ้น
- หลีกเลี่ยง Subquery ที่ซับซ้อน: พยายามเขียน Subquery ให้สั้นและชัดเจน
- ทดสอบประสิทธิภาพ: ตรวจสอบประสิทธิภาพของ query ด้วยเครื่องมือต่างๆ เช่น
EXPLAINเพื่อดูว่า query ทำงานอย่างไร และมีจุดใดที่สามารถปรับปรุงได้ - พิจารณาใช้
JOIN: หากประสิทธิภาพเป็นสิ่งสำคัญ ให้พิจารณาใช้JOINแทน Subquery
สรุป
Subquery ใน SELECT Clause เป็นเครื่องมือที่มีประโยชน์ในการดึงข้อมูลเพิ่มเติมที่เกี่ยวข้องกับแต่ละแถวที่เราเลือกจากตารางหลัก อย่างไรก็ตาม ควรใช้ Subquery อย่างระมัดระวัง โดยคำนึงถึงประสิทธิภาพและความซับซ้อนของ query การทำความเข้าใจข้อจำกัดและแนวปฏิบัติที่ดี จะช่วยให้คุณสามารถใช้ Subquery ได้อย่างมีประสิทธิภาพและหลีกเลี่ยงปัญหาที่อาจเกิดขึ้น