PlusMagi's Blog By Pitt Phunsanit Database,Programming,SQL Server การสร้าง Table อ้างอิง (Reference Table ), ตารางอันตรภาคชั้น (Class Interval )แบบที่ 3 Dynamic

การสร้าง Table อ้างอิง (Reference Table ), ตารางอันตรภาคชั้น (Class Interval )แบบที่ 3 Dynamic

จากที่ออกแบบ คณิตศาสตร์: อันตรภาคชั้น (Class Interval) แบบ 1 มีจุดอ่อนในการออกรายงาน ถ้าต้องการเน้นย้ำช่วง min – max ของแต่ละอันตรภาค เห็นเหมือนที่ BA ออกแบบมาใน excel เลย ส่วนแบบที่ 2 มีจุดอ่อนที่สำคัญคือ SQL มัน fixed ค่าไว้ไม่ได้ dynamic ถ้ามีการแก้ค่าในตาราง จะต้องมาไล่แก้ SQL แล้วแบบนี้จะทำตารางเก็บ config ให้มีโอกาสขัดแย้งระหว่าง ตาราง / SQL QUERY ทำไม่ (user ไปแก้ในตาราง แต่ไม่บอก DEV ว่าต้องแก้ query ด้วยนะ, QA, SA ไม่รู้ว่ามีแก้ตาราง, BA เข้าใจมาตลอดว่า แก้จุดเดียว) เพราะมันไม่ได้ใช้ข้อมูลเงื่อนไขจากจุดเดียว ทำให้ต้องการ redesign งานชิ้นนี้กันใหม่อีกครั้ง


ตารางเก็บข้อมูลเดิม

Table: brain_development_stages

stage_idstage_namemin_agemax_agekey_characteristic
1Childhood08Rapid Growth (3y focus)
2Adolescence (Restructuring) 931High Neuroplasticity / Emotional focus
3Golden Age (Adult) 3265Peak Stability & Efficiency
4Early Senior6682Gradual Decline
5Late Senior83150Significant Connection Loss

GET Table DYNAMIC

Table: brain_development_stages

table_idstage_namemin_agemax_agekey_characteristic
1Childhood08Rapid Growth (3y focus)
3Adolescence (Restructuring) 931High Neuroplasticity / Emotional focus
15Golden Age (Adult) 3265Peak Stability & Efficiency
4Early Senior6682Gradual Decline
2Late Senior83150Significant Connection Loss

สิ่งที่ต่างกันก็คือ

  1. column แรกเพิ่ม PK ชื่อ table_id id เข้ามาเพื่อ ความสดวกในการอ้างอิงในการ edit, delete
    • จะเห็นว่า id 15 มันโดด จำลองการที่เพิ่ม ลบ เปลี่ยนแปลงช่วงอายุ
  2. ตารางถูกออกแบบให้ เรียงตาม min_age เพื่อให้ง่ายในการอ่านโดยตามนุษย์
  3. stage_id เดิมใช้เพื่อบอกว่ามันเป็นขั้นไหน แต่ตอนนี้เราจะใช้จากลำดับ ORDER BY min_age แทน

GET config by range

WITH DynamicStages AS (-- 1. ใช้ ROW_NUMBER () เพื่อสร้าง stage_order จากลำดับแถวตามเงื่อนไข (min_age) -- 2. ใช้ LEAD () เพื่อคำนวณช่วง end_range อัตโนมัติ SELECT ROW_NUMBER () OVER (ORDER BY min_age) AS stage_order, -- ลำดับที่รันตามอายุ stage_name, key_characteristic, min_age AS start_range, COALESCE (max_age, LEAD (min_age) OVER (ORDER BY min_age) - 1, 150) AS end_range FROM brain_development_stages) -- นำมา Join กับตารางหลักเพื่อแสดงผลเรียงตามอายุ
SELECT u.age, ds.stage_order, ds.stage_name, ds.key_characteristic, ds.start_range, ds.end_range
FROM Users u
LEFT JOIN DynamicStages ds ON u.age >= ds.start_range AND u.age <= ds.end_range
ORDER BY u.age ASC;

รายละเอียดการทำงานแบบ Dynamic

  1. ดึงข้อมูลจากตาราง (Dynamic Metadata) : ชื่อช่วงอย่าง ‘Golden Age (Adult) ‘ และลักษณะเด่น ‘Peak Stability & Efficiency’ จะถูกดึงมาจากตาราง brain_development_stages โดยตรง หากคุณไปแก้ชื่อในตาราง ผลลัพธ์ใน Query นี้จะเปลี่ยนตามทันที
  2. ช่วงอายุยืดหยุ่น (Dynamic Boundaries) : ตัวเลข 32 หรือ 66 จะถูกอ่านจากคอลัมน์ min_age ในตาราง ไม่มีการ Fix ค่าใน SQL
  3. ดึงข้อมูลจากตาราง (Dynamic Metadata) : จากลำดับแถวตามเงื่อนไข (min_age) หรือค่าที่เป็นแกนหลักอื่น ๆ
  4. stage_order: ใช้ ROW_NUMBER () ซึ่งจะนับ 1, 2, 3… ไปตามลำดับของ min_age วิธีนี้ทำให้คุณไม่ต้องพึ่งพา stage_id จากตารางเดิม (ซึ่งบางครั้ง ID อาจจะไม่เรียงกันจากการลบหรือเพิ่มข้อมูล) และไม่ต้อง update stage_id ถ้าเปลี่ยนอันตรภาคชั้น
    1. Fully Dynamic: หากคุณเพิ่มช่วงอายุใหม่เข้าไปในตาราง brain_development_stages เช่น ช่วงอายุ 25 ปี (จุดที่สมองพัฒนาเต็มที่) ตัว stage_order จะขยับลำดับให้เอง และ end_range ของแถวก่อนหน้าจะหดกลับมาเชื่อมกันโดยอัตโนมัติ
    2. Order Consistency: การสั่ง ORDER BY u.age ASC ที่ท้าย Query จะช่วยให้คุณตรวจสอบความถูกต้องได้ง่ายว่า stage_order เปลี่ยนไปตามลำดับอายุที่เพิ่มขึ้นจริงหรือไม่

การเปลี่ยนแนวคิดในบางจุด ทำให้การออกแบบตารางมีประโยชน์มากกว่าแค่การเก็บข้อมูล