Tag Archive รายงาน

Byphunsanit

การสร้าง 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 เปลี่ยนไปตามลำดับอายุที่เพิ่มขึ้นจริงหรือไม่

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