ในฐานะ System Specialist และ Senior Architect ที่ต้องออกแบบระบบข้อมูลขนาดใหญ่ (Enterprise Data Architecture) เรามักจะพบกับปัญหาที่เรียกว่า ‘ข้อมูลแบบลำดับชั้น’ (Hierarchical Data) ไม่ว่าจะเป็นโครงสร้างองค์กร, ระบบไฟล์ หรือรายการหมวดหมู่สินค้า ซึ่งการดึงข้อมูลเหล่านี้ด้วยคำสั่ง SQL ทั่วไปนั้นทำได้ยากและซับซ้อน
ในโลกของ PostgreSQL มีเครื่องมือที่ทรงพลังอย่างยิ่งในการแก้ไขปัญหานี้ นั่นคือ Recursive Common Table Expressions (CTE) หรือ Recursive CTEs ซึ่งเป็นคุณสมบัติขั้นสูงที่ช่วยให้เราสามารถวนลูปการค้นหาข้อมูลตามความสัมพันธ์แบบพ่อแม่-ลูก (Parent-Child Relationship) ได้อย่างมีประสิทธิภาพและอ่านง่ายกว่าการใช้ Stored Procedure แบบเดิมๆ
💡 หลักการทำงานของ Recursive CTE ใน PostgreSQL
Recursive CTE คือชุดคำสั่ง WITH RECURSIVE ที่ประกอบด้วยสองส่วนหลักที่เชื่อมต่อกันด้วย UNION ALL:
- Anchor Member (สมาชิกจุดยึด): ส่วนแรกสุด ทำหน้าที่เป็นจุดเริ่มต้นของการวนลูป โดยจะเลือกข้อมูลแถวแรกหรือระดับบนสุดของโครงสร้าง
- Recursive Member (สมาชิกแบบเรียกซ้ำ): ส่วนที่สอง ซึ่งจะอ้างอิงถึงผลลัพธ์จาก CTE ตัวเองในรอบก่อนหน้า เพื่อขยายการค้นหาลงไปทีละระดับจนกว่าเงื่อนไขการวนลูปจะไม่เป็นจริงอีกต่อไป
🛠️ ตัวอย่างการใช้งาน: การดึงโครงสร้างองค์กร (Org Chart)
สมมติว่าเรามีตาราง employees ที่เก็บรหัสพนักงาน (employee_id), ชื่อ, และรหัสผู้จัดการ (manager_id) ซึ่งเป็นตัวกำหนดความสัมพันธ์แบบลำดับชั้น เราสามารถใช้ Recursive CTE เพื่อดึงโครงสร้างทั้งหมดออกมาได้ดังนี้:
SQL
WITH RECURSIVE org_chart AS (
-- Anchor Member: เริ่มต้นที่ CEO หรือผู้บริหารสูงสุด (ไม่มี manager_id)
SELECT
employee_id,
name,
manager_id,
1 AS level -- ระดับ 1 คือระดับบนสุด
FROM employees
WHERE manager_id IS NULL
UNION ALL
-- Recursive Member: ค้นหาพนักงานที่รายงานต่อผู้จัดการในรอบก่อนหน้า
SELECT
e.employee_id,
e.name,
e.manager_id,
oc.level + 1 -- เพิ่มระดับขึ้นไปอีก 1 ระดับ
FROM employees e
JOIN org_chart oc ON e.manager_id = oc.employee_id
)
SELECT * FROM org_chart ORDER BY level, employee_id;
🔍 การวิเคราะห์โค้ด (Architectural Deep Dive)
WITH RECURSIVE org_chart AS (...): ประกาศ CTE ชื่อorg_chartและระบุว่าเป็นแบบเรียกซ้ำ- Anchor Member: ส่วนแรกจะเลือกพนักงานที่ไม่มีผู้จัดการ (ระดับสูงสุด) เพื่อให้การวนลูปเริ่มต้นได้
- Recursive Member: ส่วนนี้คือหัวใจสำคัญ โดยมันทำการ
JOINตารางemployeesกับผลลัพธ์ของ CTE ตัวเอง (org_chart oc) เมื่อรันไปเรื่อยๆ มันจะหาพนักงานที่e.manager_idตรงกับoc.employee_idในรอบก่อนหน้า ทำให้เกิดการขยายข้อมูลลงมาเป็นชั้นๆ
✅ สรุปและแนวปฏิบัติที่ดีที่สุด (Conclusion)
Recursive CTEs เป็นเครื่องมือที่ขาดไม่ได้สำหรับนักพัฒนาระบบที่ต้องจัดการกับโครงสร้างข้อมูลแบบ Tree หรือ Graph ใน PostgreSQL การทำความเข้าใจการแยกส่วน Anchor และ Recursive Member อย่างชัดเจน จะช่วยให้คุณสามารถออกแบบ Query ที่ซับซ้อนได้อย่างมีประสิทธิภาพ
เมื่อนำไปใช้งานจริง ควรระมัดระวังเรื่องขนาดของชุดข้อมูล (Data Volume) เนื่องจาก CTEs มีแนวโน้มที่จะใช้ทรัพยากรสูง หากโครงสร้างมีความลึกมากเกินไป การปรับปรุง Index บนคอลัมน์ความสัมพันธ์ (เช่น manager_id) จึงเป็นสิ่งสำคัญอย่างยิ่งเพื่อรักษาประสิทธิภาพการทำงานของระบบในระดับ Production