การทำ Pivot ด้วยการรวมตามเงื่อนไข
รูปแบบ CASE ภายใน SUM ที่ใช้ได้กับหลายระบบ เพื่อเปลี่ยนแถวเป็นคอลัมน์
การทำ Pivot ด้วยการรวมตามเงื่อนไข เป็นบทเรียน SQL Interview Prep ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน SQL Interview Prep และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส SQL Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน
โจทย์ในการสัมภาษณ์
โจทย์ด้านการรายงานที่พบบ่อยมากในการสัมภาษณ์คือ การแปลงแถวให้เป็นคอลัมน์ คุณมีตารางแบบยาว เช่น sales(region, quarter, amount) และผู้สัมภาษณ์ต้องการรายงานแบบกว้างที่มีหนึ่งคอลัมน์ต่อไตรมาส
คำตอบที่ใช้ได้กับระบบต่าง ๆ และไม่ขึ้นกับภาษาย่อยที่พวกเขาต้องการฟังคือ การรวมแบบมีเงื่อนไข: วางนิพจน์ CASE ไว้ภายในฟังก์ชันรวม เช่น SUM หากเข้าใจรูปแบบนี้ คุณก็สามารถแปลงข้อมูลเป็นตารางไขว้ในฐานข้อมูลใด ๆ ได้ แม้แต่ฐานข้อมูลที่ไม่มีคีย์เวิร์ด PIVOT
รูปแบบยาวเทียบกับรูปแบบกว้าง
ก่อนแปลงข้อมูลเป็นตารางไขว้ ให้เรียกชื่อรูปแบบข้อมูลให้ถูกต้องก่อน รูปแบบยาวเก็บข้อเท็จจริงหนึ่งรายการต่อแถว ดังนั้นคู่ภูมิภาคและไตรมาสแต่ละคู่จึงเป็นแถวของตนเอง ส่วน รูปแบบกว้างจะกระจายหมวดหมู่ไปตามคอลัมน์
- แบบยาว: เพิ่มข้อมูลได้ง่าย แต่อ่านเปรียบเทียบกันทีละคอลัมน์ได้ยาก
- แบบกว้าง: เหมาะมากสำหรับรายงานที่นำเสนอให้คนอ่าน
การแปลงข้อมูลเป็นตารางไขว้จะแปลงรูปแบบยาวให้เป็นรูปแบบกว้าง ผู้สัมภาษณ์ชอบโจทย์นี้เพราะใช้ทดสอบว่าคุณเข้าใจการรวมข้อมูล ไม่ใช่แค่ไวยากรณ์
-- Long form (the input)
region | quarter | amount
-------+---------+-------
East | Q1 | 100
East | Q2 | 150
West | Q1 | 200
West | Q2 | 250รูปแบบหลัก
เคล็ดลับคือ สำหรับคอลัมน์ผลลัพธ์แต่ละคอลัมน์ ให้เขียน CASE ที่คืนค่าเมื่อแถวนั้นตรงกับคอลัมน์ดังกล่าว และคืนค่า NULL ในกรณีอื่น จากนั้นครอบด้วยฟังก์ชันรวม เพื่อยุบแต่ละกลุ่มให้เหลือหนึ่งแถวต่อคีย์
ให้อ่านความหมายว่า: หาผลรวมของ amount แต่เฉพาะแถว Q1 เท่านั้น เนื่องจาก SUM จะไม่สนใจ NULL แถวที่ไม่ตรงเงื่อนไขจึงไม่มีส่วนเพิ่มในผลรวม
SELECT
region,
SUM(CASE WHEN quarter = 'Q1' THEN amount END) AS q1,
SUM(CASE WHEN quarter = 'Q2' THEN amount END) AS q2
FROM sales
GROUP BY region;เหตุใด SUM จึงไม่สนใจ NULL
รูปแบบนี้ทำงานได้เพราะข้อเท็จจริงข้อหนึ่งที่ผู้สัมภาษณ์มักถามต่อ: ฟังก์ชันรวมจะข้ามค่า NULL CASE ที่ไม่มี ELSE จะคืนค่า NULL เมื่อไม่มีแขนงใดตรงเงื่อนไข ดังนั้น SUM(CASE WHEN ... THEN amount END) จึงเพิ่มเฉพาะแถวที่คุณเลือกไว้
หากเขียน ELSE 0 แทน ก็ยังใช้ได้กับ SUM (การบวกศูนย์ไม่เปลี่ยนผลลัพธ์) แต่จะทำให้ AVG, MIN และ COUNT ให้ผลไม่ถูกต้อง
-- Both produce the same SUM result:
SUM(CASE WHEN quarter = 'Q1' THEN amount END)
SUM(CASE WHEN quarter = 'Q1' THEN amount ELSE 0 END)ตัวอย่างแบบลงมือทำ: รายงานรายไตรมาส
นี่คือคำสั่งค้นหาฉบับเต็มที่ใช้กับข้อมูลตัวอย่าง แต่ละภูมิภาคจะกลายเป็นหนึ่งแถว และแต่ละไตรมาสจะกลายเป็นหนึ่งคอลัมน์
GROUP BY region คือสิ่งที่รวมแถวข้อมูลเข้าทั้งสี่แถวให้เหลือแถวผลลัพธ์สองแถว หากไม่มีส่วนนี้ คุณจะได้หนึ่งแถวต่อหนึ่งแถวข้อมูลเข้า โดยส่วนใหญ่จะมีค่า NULL
SELECT
region,
SUM(CASE WHEN quarter = 'Q1' THEN amount END) AS q1,
SUM(CASE WHEN quarter = 'Q2' THEN amount END) AS q2
FROM sales
GROUP BY region;
-- Result:
-- region | q1 | q2
-- East | 100 | 150
-- West | 200 | 250การเลือกฟังก์ชันรวมค่าที่เหมาะสม
ฟังก์ชันรวมค่าที่ครอบ CASE ต้องสอดคล้องกับคำถาม:
SUMเมื่อแต่ละช่องต้องรวมค่าMAXหรือMINเมื่อแต่ละคู่ภูมิภาค/ไตรมาสมีค่าเพียงค่าเดียว และคุณเพียงต้องการแสดงค่านั้นCOUNTเมื่อแต่ละช่องต้องนับแถวที่ตรงเงื่อนไข
ผู้สัมภาษณ์มักถามรูปแบบ COUNT เช่น แต่ละสถานะมีคำสั่งซื้อกี่รายการในแต่ละเดือน
SELECT
month,
COUNT(CASE WHEN status = 'shipped' THEN 1 END) AS shipped,
COUNT(CASE WHEN status = 'cancelled' THEN 1 END) AS cancelled
FROM orders
GROUP BY month;ใช้ MAX กับช่องที่มีค่าเดียว
เมื่อแต่ละคู่คีย์/หมวดหมู่มีค่าเพียงค่าเดียว (เป็นตารางไขว้จริง ไม่ใช่ผลรวม) ให้ใช้ MAX หรือ MIN ทั้งสองแบบจะคืนค่าที่ไม่ใช่ NULL เพียงค่าเดียว และไม่สนใจค่า NULL จากแขนงที่ไม่ตรงเงื่อนไข
นี่เป็นตัวเลือกที่ปลอดภัยเมื่อคุณกำลังปรับรูปแบบคุณลักษณะ แทนที่จะรวมยอดเงิน เช่น เปลี่ยนตารางการตั้งค่าแบบคีย์/ค่าให้เป็นหนึ่งแถวต่อหนึ่งเอนทิตี
-- Turn key/value rows into one wide row per user
SELECT
user_id,
MAX(CASE WHEN attr = 'city' THEN value END) AS city,
MAX(CASE WHEN attr = 'plan' THEN value END) AS plan
FROM user_attributes
GROUP BY user_id;การจัดการช่องผลลัพธ์ที่เป็น NULL
หากภูมิภาคหนึ่งไม่มียอดขายในไตรมาส 2 ช่อง q2 ของภูมิภาคนั้นจะมีค่าเป็น NULL ผู้สัมภาษณ์อาจขอให้คุณแสดงค่า 0 แทน ให้ครอบฟังก์ชันรวมค่าทั้งหมดด้วย COALESCE
วาง COALESCE ไว้ด้านนอกฟังก์ชันรวมค่า ไม่ใช่ด้านใน CASE เพื่อให้แทนค่าเฉพาะเมื่อทั้งกลุ่มไม่มีแถวที่ตรงเงื่อนไข
SELECT
region,
COALESCE(SUM(CASE WHEN quarter = 'Q1' THEN amount END), 0) AS q1,
COALESCE(SUM(CASE WHEN quarter = 'Q2' THEN amount END), 0) AS q2
FROM sales
GROUP BY region;การเพิ่มคอลัมน์ผลรวมทั้งหมด
คำถามต่อยอดที่พบบ่อยคือ ให้เพิ่มผลรวมของคอลัมน์ที่หมุนตารางทั้งหมด คุณไม่จำเป็นต้องบวกคอลัมน์ทีละชื่อ การใช้ SUM(amount) แบบปกติกับกลุ่มเดิมจะให้ผลรวมของแถว เพราะไม่ได้ใช้การกรองของ CASE เลย
สิ่งนี้แสดงให้ผู้สัมภาษณ์เห็นว่าคุณเข้าใจว่าแต่ละฟังก์ชันรวมค่าใน SELECT จะคำนวณแยกจากกันบนกลุ่มเดิม
SELECT
region,
SUM(CASE WHEN quarter = 'Q1' THEN amount END) AS q1,
SUM(CASE WHEN quarter = 'Q2' THEN amount END) AS q2,
SUM(amount) AS total
FROM sales
GROUP BY region;ทางลัดสำหรับฟังก์ชันรวมค่าแบบกรอง
PostgreSQL และมาตรฐาน SQL รองรับ FILTER (WHERE ...) ซึ่งเป็นวิธีเขียนการรวมค่าแบบมีเงื่อนไขที่กระชับกว่า อ่านเข้าใจได้ดีกว่า และหลีกเลี่ยงโค้ดส่วนเกินของ CASE
กล่าวถึงวิธีนี้ในการสัมภาษณ์เพื่อแสดงความรู้ที่หลากหลาย แต่ควรทราบว่า MySQL และเซิร์ฟเวอร์ SQL ไม่รองรับ ดังนั้น CASE จึงยังเป็นคำตอบที่ใช้ข้ามระบบได้
-- Postgres / standard SQL
SELECT
region,
SUM(amount) FILTER (WHERE quarter = 'Q1') AS q1,
SUM(amount) FILTER (WHERE quarter = 'Q2') AS q2
FROM sales
GROUP BY region;ข้อจำกัดสำคัญ
การรวมค่าแบบมีเงื่อนไขมีข้อควรระวังหนึ่งเรื่องที่ผู้สัมภาษณ์มักถามต่อ: คุณต้องระบุคอลัมน์ผลลัพธ์ทุกคอลัมน์ด้วยตนเอง หากไม่ทราบไตรมาสหรือหมวดหมู่ล่วงหน้า คำสั่งแบบตายตัวนี้จะปรับตามข้อมูลไม่ได้
ปัญหานี้เรียกว่า การหมุนตารางแบบไดนามิก และต้องใช้ SQL ที่สร้างขึ้นมา สำหรับชุดหมวดหมู่ที่ตายตัวและทราบแน่นอน การรวมค่าแบบมีเงื่อนไขยังคงเป็นตัวเลือกที่สะอาดและใช้ข้ามระบบได้ดีที่สุด
ตรวจสอบความเข้าใจ
ทดสอบความเข้าใจรูปแบบการรวมค่าแบบมีเงื่อนไขของคุณ
สรุป
การรวมค่าแบบมีเงื่อนไขคือการหมุนตารางที่ใช้ข้ามระบบได้ ซึ่งผู้สัมภาษณ์ทุกคนยอมรับ:
- ใช้
CASEหนึ่งชุดต่อหนึ่งคอลัมน์ผลลัพธ์ แล้วครอบด้วยฟังก์ชันรวมค่า - ใช้
SUMสำหรับผลรวม ใช้MAX/MINสำหรับช่องที่มีค่าเดียว และใช้COUNTสำหรับการนับ - ทำงานได้เพราะฟังก์ชันรวมค่าไม่สนใจค่า
NULLจากแขนงที่ไม่ตรงเงื่อนไข - ใช้
COALESCEเพื่อเปลี่ยนช่องว่างให้เป็น 0 - ข้อจำกัด: ต้องกำหนดคอลัมน์ตายตัวในคำสั่ง จึงจะนำไปสู่การหมุนตารางแบบไดนามิกในหัวข้อต่อไป
เรียนรู้ SQL ด้วย AI tutor — ฟรี
เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป
- คอร์ส
- 30
- บทเรียน
- 120
คำถามที่พบบ่อย
บทเรียน “การทำ Pivot ด้วยการรวมตามเงื่อนไข” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การทำ Pivot ด้วยการรวมตามเงื่อนไข” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส SQL Interview Prep ให้อัปเกรดเป็น CoddyKit PRO คอร์ส SQL Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การทำ Pivot ด้วยการรวมตามเงื่อนไข”
รูปแบบ CASE ภายใน SUM ที่ใช้ได้กับหลายระบบ เพื่อเปลี่ยนแถวเป็นคอลัมน์ คุณปฏิบัติ SQL Interview Prep ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน SQL Interview Prep หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน SQL Interview Prep บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน
บทเรียน “การทำ Pivot ด้วยการรวมตามเงื่อนไข” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน SQL Interview Prep นี้ได้ไหม
ได้ บทเรียน SQL Interview Prep ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การทำ Pivot ด้วยการรวมตามเงื่อนไข
- ไวยากรณ์ PIVOT และ Crosstab เฉพาะระบบ
- เปลี่ยนคอลัมน์กลับเป็นแถว
- Pivot แบบไดนามิกเมื่อไม่ทราบคอลัมน์ล่วงหน้า