จากที่ออกแบบ คณิตศาสตร์: อันตรภาคชั้น (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_id | stage_name | min_age | max_age | key_characteristic |
| 1 | Childhood | 0 | 8 | Rapid Growth (3y focus) |
| 2 | Adolescence (Restructuring) | 9 | 31 | High Neuroplasticity / Emotional focus |
| 3 | Golden Age (Adult) | 32 | 65 | Peak Stability & Efficiency |
| 4 | Early Senior | 66 | 82 | Gradual Decline |
| 5 | Late Senior | 83 | 150 | Significant Connection Loss |
GET Table DYNAMIC
Table: brain_development_stages
| table_id | stage_name | min_age | max_age | key_characteristic |
| 1 | Childhood | 0 | 8 | Rapid Growth (3y focus) |
| 3 | Adolescence (Restructuring) | 9 | 31 | High Neuroplasticity / Emotional focus |
| 15 | Golden Age (Adult) | 32 | 65 | Peak Stability & Efficiency |
| 4 | Early Senior | 66 | 82 | Gradual Decline |
| 2 | Late Senior | 83 | 150 | Significant Connection Loss |
สิ่งที่ต่างกันก็คือ
- column แรกเพิ่ม PK ชื่อ table_id id เข้ามาเพื่อ ความสดวกในการอ้างอิงในการ edit, delete
- จะเห็นว่า id 15 มันโดด จำลองการที่เพิ่ม ลบ เปลี่ยนแปลงช่วงอายุ
- ตารางถูกออกแบบให้ เรียงตาม min_age เพื่อให้ง่ายในการอ่านโดยตามนุษย์
- 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
- ดึงข้อมูลจากตาราง (Dynamic Metadata): ชื่อช่วงอย่าง ‘Golden Age (Adult)’ และลักษณะเด่น ‘Peak Stability & Efficiency’ จะถูกดึงมาจากตาราง
brain_development_stagesโดยตรง หากคุณไปแก้ชื่อในตาราง ผลลัพธ์ใน Query นี้จะเปลี่ยนตามทันที - ช่วงอายุยืดหยุ่น (Dynamic Boundaries): ตัวเลข 32 หรือ 66 จะถูกอ่านจากคอลัมน์
min_ageในตาราง ไม่มีการ Fix ค่าใน SQL - ดึงข้อมูลจากตาราง (Dynamic Metadata): จากลำดับแถวตามเงื่อนไข (min_age) หรือค่าที่เป็นแกนหลักอื่น ๆ
stage_order: ใช้ROW_NUMBER()ซึ่งจะนับ 1, 2, 3… ไปตามลำดับของmin_ageวิธีนี้ทำให้คุณไม่ต้องพึ่งพาstage_idจากตารางเดิม (ซึ่งบางครั้ง ID อาจจะไม่เรียงกันจากการลบหรือเพิ่มข้อมูล) และไม่ต้อง updatestage_idถ้าเปลี่ยนอันตรภาคชั้น- Fully Dynamic: หากคุณเพิ่มช่วงอายุใหม่เข้าไปในตาราง
brain_development_stagesเช่น ช่วงอายุ 25 ปี (จุดที่สมองพัฒนาเต็มที่) ตัวstage_orderจะขยับลำดับให้เอง และend_rangeของแถวก่อนหน้าจะหดกลับมาเชื่อมกันโดยอัตโนมัติ - Order Consistency: การสั่ง
ORDER BY u.age ASCที่ท้าย Query จะช่วยให้คุณตรวจสอบความถูกต้องได้ง่ายว่าstage_orderเปลี่ยนไปตามลำดับอายุที่เพิ่มขึ้นจริงหรือไม่
- Fully Dynamic: หากคุณเพิ่มช่วงอายุใหม่เข้าไปในตาราง
การเปลี่ยนแนวคิดในบางจุด ทำให้การออกแบบตารางมีประโยชน์มากกว่าแค่การเก็บข้อมูล
