jsTree: HTML data

ในการพัฒนาแอปพลิเคชันที่ต้องแสดงโครงสร้างข้อมูลแบบลำดับชั้น (Hierarchical Data) เช่น ระบบหมวดหมู่สินค้า, แผนผังองค์กร, หรือเมนูเว็บไซต์ การจัดการความสัมพันธ์แบบ Parent-Child ถือเป็นหัวใจสำคัญของระบบฐานข้อมูล

แม้ว่าไลบรารี JavaScript อย่าง jsTree จะถูกใช้ในการแสดงผลข้อมูลในรูปแบบ Tree บนฝั่ง Front-end แต่รากฐานที่แข็งแกร่งของข้อมูลนั้นต้องมาจาก Back-end ที่มีประสิทธิภาพสูง ซึ่งในบริบทของฐานข้อมูล PostgreSQL นั้น เครื่องมือที่ทรงพลังที่สุดในการจัดการความสัมพันธ์แบบลำดับชั้นคือ Recursive Common Table Expressions (CTE)

💡 หลักการทำงาน: การสร้างโครงสร้าง Tree ใน PostgreSQL

โดยปกติแล้ว การเก็บข้อมูลแบบลำดับชั้นจะถูกออกแบบโดยมีคอลัมน์ที่ระบุ parent_id ซึ่งชี้ไปยัง Primary Key ของแถวแม่ (Parent) ทำให้เกิดความสัมพันธ์แบบ One-to-Many หากเราต้องการดึงข้อมูลทั้งหมดออกมาในรูปแบบโครงสร้างต้นไม้ (Tree Structure) แบบสมบูรณ์ การใช้คำสั่ง SELECT ธรรมดาจะไม่เพียงพอ

Recursive CTE คือคำสั่งที่อนุญาตให้เราเรียกใช้ชุดคำสั่ง SQL ซ้ำๆ (Recursively) จนกว่าเงื่อนไขที่กำหนดจะสิ้นสุดลง ทำให้ PostgreSQL สามารถไล่ระดับความสัมพันธ์จากราก (Root) ลงไปยังโหนดลูก (Leaf) ได้อย่างเป็นธรรมชาติและมีประสิทธิภาพ

⚙️ ตัวอย่างโค้ด: การดึงข้อมูลโครงสร้างแบบ Tree

สมมติว่าเรามีตาราง categories ที่เก็บข้อมูลหมวดหมู่สินค้า โดยมีคอลัมน์ id, name, และ parent_id:

SQL

-- 1. สร้างตารางจำลอง (Setup Table) ----------------------------------
CREATE TABLE categories (
    id INT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    parent_id INT REFERENCES categories(id)
);

-- 2. ใส่ข้อมูลตัวอย่าง (Data Insertion) ----------------------------------
INSERT INTO categories (id, name, parent_id) VALUES
(1, 'Electronics', NULL),
(2, 'Apparel', NULL),
(3, 'Smartphones', 1),
(4, 'Laptops', 1),
(5, 'T-Shirts', 2),
(6, 'Jeans', 2),
(7, 'iPhone Series', 3);

-- 3. ใช้ Recursive CTE เพื่อดึงโครงสร้างแบบ Tree --------------------------
WITH RECURSIVE category_tree AS (
    -- Anchor Member: เริ่มต้นที่โหนดราก (Root Nodes) 
    SELECT id, name, parent_id, 1 AS level, CAST(name AS TEXT) AS path
    FROM categories
    WHERE parent_id IS NULL

    UNION ALL

    -- Recursive Member: ทำซ้ำเพื่อค้นหาโหนดลูก 
    SELECT c.id, c.name, c.parent_id, t.level + 1, t.path || ' > ' || c.name
    FROM categories c
    JOIN category_tree t ON c.parent_id = t.id
)
SELECT id, name, parent_id, level, path
FROM category_tree
ORDER BY level, id;

คำอธิบายโค้ด:

  • Anchor Member: กำหนดจุดเริ่มต้นของการเรียกซ้ำ (ในที่นี้คือหมวดหมู่ที่ไม่มี parent_id หรือโหนดราก)
  • Recursive Member: ทำหน้าที่เชื่อมโยง (JOIN) ข้อมูลในรอบก่อนหน้า (category_tree t) เข้ากับตารางหลัก categories c โดยใช้เงื่อนไข c.parent_id = t.id
  • ผลลัพธ์: CTE จะขยายความสัมพันธ์ลงไปเรื่อยๆ จนกว่าจะครอบคลุมทุกโหนดลูก ทำให้เราได้ชุดข้อมูลที่สมบูรณ์พร้อมลำดับชั้น

🚀 การนำข้อมูลไปใช้กับ Front-end (jsTree)

เมื่อ PostgreSQL ประมวลผลด้วย Recursive CTE แล้ว ผลลัพธ์ที่ได้คือชุดข้อมูลที่มีความสัมพันธ์ลำดับชั้นที่สมบูรณ์ (Structured Data) นักพัฒนาจะทำการดึงข้อมูลนี้ออกมาในรูปแบบ JSON (หรือ XML) จาก API Endpoint ของ Back-end (เช่น Python/Node.js) จากนั้นจึงส่ง JSON นี้ไปยัง Front-end เพื่อให้ไลบรารีอย่าง jsTree นำไปสร้างเป็นองค์ประกอบ DOM (Document Object Model) ที่สวยงามและใช้งานได้จริง

✅ บทสรุป

การจัดการข้อมูลแบบ Tree Structure ไม่ใช่แค่การเชื่อมโยง Parent-Child แต่คือการจัดการความสัมพันธ์ที่ซับซ้อน การใช้ Recursive CTE ใน PostgreSQL จึงเป็น Best Practice ที่สุดสำหรับงานประเภทนี้ เพราะไม่เพียงแต่ให้ความแม่นยำของข้อมูล แต่ยังช่วยให้โค้ด SQL มีประสิทธิภาพสูงในการดึงข้อมูลโครงสร้างทั้งหมดออกมาในครั้งเดียว ทำให้ระบบ Back-end มีความเสถียรและพร้อมรองรับการแสดงผลที่ซับซ้อนบน Front-end ได้อย่างสมบูรณ์