วัน: 2 มีนาคม 2021

PrimeReact Case Study: การทำ Dropdown, MultiSelect และ Cascades Select ข้อมูลแบบเชื่อมโยงกันPrimeReact Case Study: การทำ Dropdown, MultiSelect และ Cascades Select ข้อมูลแบบเชื่อมโยงกัน

ในโลกของการพัฒนาซอฟต์แวร์ระดับองค์กร (Enterprise Application) การสร้าง User Interface ที่ใช้งานง่ายนั้นเป็นเพียงส่วนหนึ่งของสมการเท่านั้น หัวใจสำคัญที่แท้จริงคือความสามารถในการจัดการกับความสัมพันธ์ของข้อมูลที่ซับซ้อนและมีลำดับชั้น (Hierarchical Data) ได้อย่างแม่นยำ ไม่ว่าคุณจะใช้ Frontend Framework ใดก็ตาม การดึงข้อมูลแบบ Cascades Select หรือ MultiSelect ที่มีการพึ่งพาอาศัยกันระหว่างองค์ประกอบต่างๆ จะต้องเริ่มต้นจากการออกแบบฐานข้อมูลที่แข็งแกร่ง

บทความนี้จะเจาะลึกถึงการแก้ปัญหา ‘Cascading Data’ โดยใช้พลังของ PostgreSQL ซึ่งเป็นระบบจัดการฐานข้อมูล (DBMS) ชั้นนำ ด้วยเทคนิคขั้นสูงอย่าง WITH RECURSIVE CTE และการจัดการโครงสร้างแบบลำดับชั้น เพื่อให้มั่นใจว่าข้อมูลที่ถูกส่งไปใช้งานในส่วนหน้า (Frontend) นั้นมีความถูกต้องและสอดคล้องกับตรรกะทางธุรกิจ (Business Logic) เสมอ

💡 หลักการจัดการความสัมพันธ์แบบ Cascade ใน PostgreSQL

เมื่อเราพูดถึง Cascades Select เช่น การเลือกประเทศ (Parent) แล้วจึงเลือกภูมิภาค (Child) และสุดท้ายคือเมือง (Grandchild) ความท้าทายไม่ได้อยู่ที่ UI แต่อยู่ที่การ Query ข้อมูลให้เป็นลำดับชั้น ฐานข้อมูลต้องสามารถตอบคำถามว่า ‘ถ้าฉันมี ID นี้ ฉันควรจะดึงรายการลูกทั้งหมดที่มีความสัมพันธ์กันมาอย่างไร?’

PostgreSQL มีเครื่องมือที่ทรงพลังในการจัดการปัญหานี้ นั่นคือ Recursive Common Table Expressions (CTE) ซึ่งช่วยให้เราสามารถวนซ้ำการค้นหาข้อมูลตามโครงสร้างแบบต้นไม้ (Tree Structure) ได้อย่างมีประสิทธิภาพ โดยไม่ต้องเขียนโค้ด Loop ที่ซับซ้อน

🛠️ ตัวอย่าง: การจำลอง Cascades Select ด้วย Recursive CTE

สมมติว่าเรามีตาราง categories ที่เก็บข้อมูลหมวดหมู่สินค้า โดยแต่ละรายการจะมี parent_id อ้างอิงถึง ID ของหมวดหมู่แม่

SQL

-- 1. สร้างตารางจำลองโครงสร้างลำดับชั้น (Hierarchy) --
CREATE TABLE categories (
    category_id SERIAL PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    parent_id INTEGER REFERENCES categories(category_id)
);

-- ใส่ข้อมูลตัวอย่าง: Electronics -> Laptops -> MacBook
INSERT INTO categories (name, parent_id) VALUES 
('Electronics', NULL),
('Laptops', 1),
('Smartphones', 1),
('MacBook', 2);

-- 2. ใช้ Recursive CTE เพื่อดึงข้อมูลทั้งหมดในสายงาน (Cascade)
WITH RECURSIVE category_hierarchy AS (
    -- Anchor Member: เริ่มต้นจากหมวดหมู่หลักที่ไม่มี Parent
    SELECT 
        category_id, 
        name, 
        parent_id, 
        1 AS level -- ระดับ 1 คือระดับบนสุด
    FROM categories WHERE parent_id IS NULL

    UNION ALL

    -- Recursive Member: วนซ้ำเพื่อหาลูกของแถวที่เพิ่งค้นพบ
    SELECT 
        c.category_id, 
        c.name, 
        c.parent_id, 
        ch.level + 1 -- เพิ่มระดับขึ้นไปอีก 1
    FROM categories c
    JOIN category_hierarchy ch ON c.parent_id = ch.category_id
) 
SELECT * FROM category_hierarchy ORDER BY level, category_id;

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

  • WITH RECURSIVE: เป็นหัวใจสำคัญที่ทำให้ PostgreSQL สามารถวนซ้ำการค้นหาข้อมูลได้
  • Anchor Member: กำหนดจุดเริ่มต้นของการค้นหา (เช่น หมวดหมู่หลัก)
  • Recursive Member: ใช้ JOIN กับผลลัพธ์ของ CTE ตัวเอง เพื่อดึงลูกๆ ในแต่ละระดับชั้นอย่างต่อเนื่อง ทำให้เราสามารถจำลองการทำงานแบบ Cascading ได้สมบูรณ์

🚀 ประโยชน์ทางสถาปัตยกรรม (Architectural Benefits)

การใช้ PostgreSQL และ Recursive CTE ในลักษณะนี้ ไม่เพียงแต่ช่วยให้โค้ด Query มีประสิทธิภาพเท่านั้น แต่ยังเป็นการรับประกัน ความสมบูรณ์ของข้อมูล (Data Integrity) ตั้งแต่ต้นทาง

  • ลดภาระ Frontend: แทนที่ Frontend จะต้องเรียก API หลายครั้งเพื่อหาตัวเลือกถัดไป Backend สามารถส่งโครงสร้างข้อมูลทั้งหมดในรูปแบบ JSONB ที่มีลำดับชั้นมาให้ได้ในการ Query ครั้งเดียว
  • ความยืดหยุ่นสูง: การใช้ CTE ทำให้ระบบสามารถรองรับการเพิ่มระดับของข้อมูล (เช่น จาก Country -> Region -> City เป็น Country -> Region -> State -> District) ได้โดยแทบไม่ต้องแก้ไข Logic หลัก

✅ บทสรุป

สำหรับนักพัฒนาที่ต้องการสร้างระบบที่มีความซับซ้อนของข้อมูลสูง การเข้าใจถึงกลไกการจัดการลำดับชั้นในระดับฐานข้อมูลจึงเป็นทักษะที่สำคัญกว่าการจำ Component UI ต่างๆ การใช้ PostgreSQL ร่วมกับ Recursive CTE คือคำตอบทางสถาปัตยกรรมที่มั่นคงและมีประสิทธิภาพที่สุดในการสร้างรากฐานข้อมูลสำหรับระบบ Cascading Select ที่เชื่อถือได้