ป้ายกำกับ: Unpivot

เอา Matrix มาสลับ column ใน database แนวนอนแนวตั้งเอา Matrix มาสลับ column ใน database แนวนอนแนวตั้ง

การจัดการโครงสร้างข้อมูล: Pivot และ Unpivot ใน PostgreSQL

ในโลกของการออกแบบฐานข้อมูล การจัดการโครงสร้างข้อมูลให้อยู่ในรูปแบบที่เหมาะสมเป็นสิ่งสำคัญอย่างยิ่ง การแปลงข้อมูลจากรูปแบบตารางแนวนอน (Wide Format) ไปเป็นแนวตั้ง (Long Format) และในทางกลับกัน คือกระบวนการที่เรียกว่า Pivot และ Unpivot ตามลำดับ

ในทางคณิตศาสตร์เราเรียกมันว่า Matrix Reshaping แต่ในบริบทของฐานข้อมูลเชิงสัมพันธ์ (Relational Database) การทำความเข้าใจว่าเมื่อใดควรใช้โครงสร้างแบบใด จะช่วยให้ Query มีประสิทธิภาพและง่ายต่อการบำรุงรักษาอย่างมาก บทความนี้จะเจาะลึกวิธีการทำ Pivot และ Unpivot โดยใช้ไวยากรณ์เฉพาะของ PostgreSQL

1. Unpivot (Wide to Long): การแปลงตารางแนวนอนเป็นแนวตั้ง

Unpivot คือการเปลี่ยนคอลัมน์จำนวนมาก (เช่น `create`, `read`, `update`, `delete`) ให้กลายเป็นแถวข้อมูล (Rows) โดยสร้างคอลัมน์ใหม่สำหรับชื่อสิทธิ์ (Permission) และค่าสิทธิ์ (Status) การทำเช่นนี้ทำให้ข้อมูลมีความเป็นมาตรฐาน (Normalized) มากขึ้น

สมมติว่าเรามีตาราง `user_permissions` ที่เก็บสิทธิ์แบบ Wide (เช่น ID, Program_ID, Create, Read, Update, Delete) เราสามารถใช้เทคนิค UNION ALL หรือ LATERAL JOIN เพื่อจำลองการ Unpivot:

SQL

-- ตัวอย่าง: Unpivot ตารางสิทธิ์ (Wide -> Long) 
-- Goal: เปลี่ยนคอลัมน์สิทธิ์ให้เป็นแถวข้อมูล

SELECT id, program_id, 'create' AS permission_type, status_create AS permission_status FROM wide_permissions WHERE id = 1
UNION ALL
SELECT id, program_id, 'read' AS permission_type, status_read AS permission_status FROM wide_permissions WHERE id = 1
UNION ALL
SELECT id, program_id, 'update' AS permission_type, status_update AS permission_status FROM wide_permissions WHERE id = 1;

คำอธิบาย: การใช้ UNION ALL เป็นวิธีที่ตรงไปตรงมาที่สุดในการ Unpivot ใน PostgreSQL โดยเราเลือกคอลัมน์ที่ต้องการแปลงเป็นแถวข้อมูล และกำหนดชื่อคอลัมน์ใหม่ (เช่น permission_type และ permission_status) ให้กับข้อมูลที่ถูกรวมเข้าด้วยกัน

2. Pivot (Long to Wide): การแปลงตารางแนวตั้งเป็นแนวนอน

Pivot คือการทำย้อนกลับ คือการรวมข้อมูลที่เคยอยู่ในแถว (Rows) ให้กลับไปอยู่ในคอลัมน์ (Columns) การทำ Pivot ใน SQL มักจะใช้เทคนิคที่เรียกว่า Conditional Aggregation (การรวมข้อมูลแบบมีเงื่อนไข) โดยใช้ฟังก์ชัน CASE WHEN ร่วมกับ GROUP BY

สมมติว่าเรามีตาราง `long_permissions` ที่เก็บสิทธิ์แบบ Long (ID, Program_ID, Permission_Type, Status) เราต้องการ Pivot กลับไปเป็น Wide Format:

SQL

-- ตัวอย่าง: Pivot ตารางสิทธิ์ (Long -> Wide) 
-- Goal: เปลี่ยนแถวสิทธิ์ให้กลับเป็นคอลัมน์

SELECT
    program_id,
    MAX(CASE WHEN permission_type = 'create' THEN permission_status END) AS create,
    MAX(CASE WHEN permission_type = 'read' THEN permission_status END) AS read,
    MAX(CASE WHEN permission_type = 'update' THEN permission_status END) AS update
FROM long_permissions
GROUP BY program_id;

คำอธิบาย: เราใช้ CASE WHEN เพื่อตรวจสอบค่าในคอลัมน์ permission_type หากตรงกับเงื่อนไขใด จะดึงค่า permission_status มาเก็บไว้ในคอลัมน์เสมือน (Virtual Column) และใช้ MAX() ในการรวมกลุ่ม (Aggregate) เพื่อให้แน่ใจว่าเราได้ค่าที่ถูกต้องสำหรับแต่ละคอลัมน์

บทสรุป: การเลือกโครงสร้างที่เหมาะสม

การทำความเข้าใจความแตกต่างระหว่าง Wide และ Long Format ไม่ใช่แค่การเขียนโค้ด แต่คือการออกแบบ Schema ที่มีประสิทธิภาพ การเลือกใช้โครงสร้างข้อมูลที่เหมาะสม (Normalization) จะช่วยให้ฐานข้อมูลของเรามีความยืดหยุ่น สามารถเพิ่มประเภทข้อมูลใหม่ได้ง่าย (โดยเฉพาะ Long Format) และทำให้ Query ของเราทำงานได้รวดเร็วและอ่านง่ายขึ้นเสมอ