🗄️ MySQL/MariaDB

เจาะลึก MySQL และ MariaDB: วิธีทำ Self Join และรวมข้อมูลด้วย UNION

9 นาที 17 views บันทึกเป็น PDF
เจาะลึก MySQL และ MariaDB: วิธีทำ Self Join และรวมข้อมูลด้วย UNION

อยากดึงข้อมูลในตารางเดียวกันหรือรวมผลลัพธ์จากหลายตารางใช่ไหม? มาดูวิธีใช้ Self Join และ UNION/UNION ALL แบบเข้าใจง่าย สำหรับมือใหม่หัดเขียน SQL

ทำความรู้จักกับ Self Join และทำไมต้องใช้

เวลาเราเก็บข้อมูลในฐานข้อมูล (Database) บางครั้งข้อมูลเหล่านั้นมีความสัมพันธ์กับตัวมันเอง เช่น ข้อมูลพนักงานที่ต้องระบุว่าใครเป็นหัวหน้าของใคร หากเราเก็บรายชื่อพนักงานและชื่อหัวหน้าไว้ในตารางเดียวกัน การจะดึงชื่อหัวหน้าออกมาแสดงผลจะทำได้ยากถ้าเราไม่รู้วิธีเชื่อมตารางเข้ากับตัวเอง หรือที่เรียกว่า Self Join (การเชื่อมตารางเข้ากับตัวเองเพื่อดึงข้อมูลที่สัมพันธ์กันออกมา)

ลองนึกภาพว่าคุณมีสมุดโทรศัพท์ที่มีชื่อคน และมีคอลัมน์บอกว่าคนนี้เป็นเพื่อนกับใครในสมุดเล่มเดียวกัน หากคุณต้องการทราบว่าเพื่อนของเพื่อนชื่ออะไร คุณก็ต้องเปิดสมุดเล่มเดิมซ้ำสองรอบเพื่อเทียบข้อมูล การทำ Self Join ก็คือการสั่งให้ฐานข้อมูลมองตารางตารางเดียวเป็นสองตารางแยกกัน เพื่อให้เราเปรียบเทียบข้อมูลภายในตารางนั้นได้สะดวกขึ้นนั่นเอง

การเข้าใจเรื่องนี้สำคัญมากสำหรับโปรแกรมเมอร์ เพราะระบบส่วนใหญ่ในโลกจริงมักมีโครงสร้างแบบลำดับชั้น (Hierarchy) เช่น ผังองค์กร ระบบสายงานอ้างอิง หรือแม้แต่ระบบหมวดหมู่สินค้าที่ซ้อนกันหลายชั้น ถ้าคุณดึงข้อมูลเหล่านี้ไม่เป็น คุณจะเสียเวลาเขียนโปรแกรมวนลูป (Loop - การทำงานซ้ำๆ) เพื่อดึงข้อมูลทีละบรรทัด ซึ่งทำให้โปรแกรมทำงานช้าและกินทรัพยากรเครื่องอย่างมาก

วิธีการเขียนคำสั่ง Self Join แบบพื้นฐาน

หัวใจสำคัญของการทำ Self Join คือการใช้ AS (การตั้งชื่อเล่นให้ตาราง) เพื่อแยกตารางเดิมออกเป็นสองชื่อสมมติ เพื่อให้เราสามารถอ้างอิงข้อมูลจากตารางเดียวกันได้โดยไม่สับสน เหมือนการเรียกชื่อเล่นให้เพื่อนสองคนที่มีชื่อจริงเหมือนกันเพื่อให้คุยกันรู้เรื่องว่าเราหมายถึงใคร

สมมติเรามีตาราง employees (ตารางเก็บข้อมูลพนักงาน) ที่มีคอลัมน์ id, name และ manager_id (รหัสหัวหน้างาน) หากเราต้องการดึงรายชื่อพนักงานคู่กับชื่อหัวหน้า เราต้องเชื่อมตาราง employees เข้ากับตัวมันเองโดยเทียบค่า manager_id ของพนักงานกับ id ของหัวหน้างาน

จุดที่มือใหม่มักพลาดคือการลืมตั้งชื่อเล่นให้ตาราง ทำให้ฐานข้อมูลไม่รู้ว่าเรากำลังอ้างอิงคอลัมน์จากส่วนไหนของตาราง ถ้าไม่ตั้งชื่อให้ชัดเจน ฐานข้อมูลจะฟ้อง Error (ข้อผิดพลาด) ทันที เพราะมันหาคอลัมน์ที่ซ้ำชื่อกันไม่เจอว่าควรดึงตัวไหนมาใช้งาน

-- เชื่อมตาราง employees สองชุดด้วยชื่อ e1 และ e2
SELECT e1.name AS employee_name, e2.name AS manager_name
FROM employees AS e1
LEFT JOIN employees AS e2 ON e1.manager_id = e2.id;

คำอธิบายโค้ด: e1 คือตารางพนักงานที่เราโฟกัส ส่วน e2 คือตารางเดียวกันที่ใช้หาชื่อหัวหน้า LEFT JOIN คือการสั่งให้ดึงพนักงานทุกคนออกมา แม้บางคนจะไม่มีหัวหน้าก็ตาม ส่วน ON คือเงื่อนไขการเชื่อม โดยเอารหัสหัวหน้าของพนักงานไปเทียบกับรหัสประจำตัวของหัวหน้า

ผลลัพธ์ที่ควรเห็น: ตารางจะแสดงชื่อพนักงานในคอลัมน์แรก และชื่อหัวหน้าของเขาในคอลัมน์ที่สอง ถ้าพนักงานคนไหนไม่มีหัวหน้า (เช่น CEO) คอลัมน์หัวหน้างานจะเป็นค่า NULL (ค่าว่างหรือไม่มีข้อมูล)

รวมผลลัพธ์จากหลายที่ด้วย UNION และ UNION ALL

บางครั้งเราต้องการนำข้อมูลจากหลายตารางหรือหลายเงื่อนไขมารวมเป็นก้อนเดียวกันเพื่อแสดงผล UNION (คำสั่งรวมผลลัพธ์จากหลาย Query) คือเครื่องมือที่ใช้รวมผลลัพธ์จากสองคำสั่งเข้าด้วยกัน โดยมีกฎว่าจำนวนคอลัมน์และประเภทข้อมูลต้องตรงกัน

ลองจินตนาการว่าคุณมีรายชื่อลูกค้าจากสองสาขาที่เก็บข้อมูลแยกตารางกัน หากต้องการทำรายการรายชื่อลูกค้าทั้งหมดเพื่อส่งอีเมลหาทุกคน คุณก็แค่เอาผลลัพธ์จากสาขาแรกมาวางต่อด้วยสาขาที่สอง นี่คือหน้าที่หลักของ UNION ซึ่งนอกจากจะรวมข้อมูลแล้ว มันยังช่วยตัดข้อมูลที่ซ้ำกันออกไปให้โดยอัตโนมัติด้วย

แต่ถ้าคุณต้องการเก็บข้อมูลทั้งหมดไว้โดยไม่สนว่าจะซ้ำหรือไม่ ต้องใช้ UNION ALL แทน มือใหม่มักใช้ UNION โดยไม่จำเป็น ซึ่งทำให้ฐานข้อมูลต้องทำงานหนักขึ้นเพื่อตรวจสอบข้อมูลซ้ำ ถ้าคุณมั่นใจว่าข้อมูลไม่มีทางซ้ำกัน หรือต้องการแสดงผลทั้งหมดแม้จะซ้ำ ให้เลือกใช้ UNION ALL จะทำงานได้เร็วกว่ามาก

-- รวมชื่อจากตารางพนักงานและรายชื่อผู้รับเหมา
SELECT name FROM employees
UNION
SELECT name FROM contractors;

คำอธิบายโค้ด: คำสั่งแรกดึงชื่อจากตารางพนักงาน คำสั่งที่สองดึงชื่อจากตารางผู้รับเหมา UNION จะรวมผลลัพธ์เข้าด้วยกันและลบชื่อที่ซ้ำกันออกไป หากต้องการให้แสดงทั้งหมดไม่ว่าจะซ้ำหรือไม่ ให้เปลี่ยนไปใช้ UNION ALL แทน

ผลลัพธ์ที่ควรเห็น: รายชื่อทุกคนจากทั้งสองตารางจะเรียงต่อกันเป็นคอลัมน์เดียว หากชื่อไหนมีอยู่ทั้งในตารางพนักงานและผู้รับเหมา ชื่อนั้นจะถูกแสดงเพียงครั้งเดียวในผลลัพธ์สุดท้าย

ข้อควรระวังในการใช้งาน UNION

การใช้ UNION มีข้อจำกัดที่ต้องระวังคือจำนวนคอลัมน์ในแต่ละคำสั่งต้องเท่ากันเป๊ะ หากคำสั่งแรกดึงมา 3 คอลัมน์ คำสั่งที่สองก็ต้องดึงมา 3 คอลัมน์เช่นกัน ถ้าคอลัมน์ไม่เท่ากัน ฐานข้อมูลจะปฏิเสธการทำงาน และแจ้งข้อผิดพลาดออกมาทันที

นอกจากนี้ ลำดับของคอลัมน์ก็สำคัญมาก ข้อมูลในคอลัมน์แรกของคำสั่งแรกจะถูกนำไปรวมกับข้อมูลในคอลัมน์แรกของคำสั่งที่สอง หากคุณดึงชื่อพนักงานไว้คอลัมน์แรก แต่คำสั่งที่สองดึงรหัสพนักงานไว้คอลัมน์แรก ข้อมูลของคุณจะปนกันมั่วจนใช้งานไม่ได้

อีกจุดหนึ่งที่มือใหม่มักลืมคือการเรียงลำดับผลลัพธ์ หากต้องการใช้ ORDER BY (คำสั่งเรียงลำดับข้อมูล) ให้ใส่ไว้ที่บรรทัดสุดท้ายของคำสั่งรวมเท่านั้น ฐานข้อมูลจะนำผลลัพธ์ทั้งหมดมารวมกันก่อน แล้วค่อยทำการเรียงลำดับตามที่เรากำหนดไว้ทีเดียว

-- รวมข้อมูลและเรียงลำดับผลลัพธ์
SELECT name, 'Employee' AS type FROM employees
UNION ALL
SELECT name, 'Contractor' AS type FROM contractors
ORDER BY name;

คำอธิบายโค้ด: เราเพิ่มคอลัมน์ type เข้าไปเพื่อบอกว่าชื่อนี้มาจากตารางไหน UNION ALL จะรวมข้อมูลทั้งหมดเข้าด้วยกันโดยไม่ตัดข้อมูลซ้ำ และ ORDER BY name จะทำการเรียงชื่อทั้งหมดตามตัวอักษรหลังจากรวมเสร็จแล้ว

ผลลัพธ์ที่ควรเห็น: ตารางแสดงสองคอลัมน์ คือชื่อและประเภทสถานะ โดยข้อมูลทั้งหมดจะถูกเรียงลำดับชื่อจาก ก ถึง ฮ หรือ A ถึง Z อย่างเป็นระเบียบ

เทคนิคการฝึกฝนเพื่อก้าวสู่โปรแกรมเมอร์มืออาชีพ

การเรียนรู้เรื่อง Self Join หรือ UNION ไม่ใช่แค่การท่องจำคำสั่ง แต่คือการฝึกคิดเชิงตรรกะว่าเราจะดึงข้อมูลที่ซับซ้อนออกมาให้ง่ายได้อย่างไร ลองหาโจทย์จากเว็บไซต์ฝึกเขียน SQL (ภาษาสำหรับจัดการฐานข้อมูล) แล้วลองแก้ปัญหาด้วยวิธีเหล่านี้ดู

สำหรับคนที่กำลังเตรียมตัวสัมภาษณ์งาน ให้ฝึกเขียนเคสจำลอง เช่น การสร้างผังองค์กร หรือการทำระบบสมาชิกที่แนะนำคนอื่นต่อกัน (Referral System) การใช้ Self Join ในสถานการณ์จริงจะช่วยให้คุณอธิบายได้ฉะฉานตอนสัมภาษณ์ว่าคุณเข้าใจโครงสร้างข้อมูลระดับลึก ไม่ใช่แค่การดึงข้อมูลจากตารางเดียว

อย่าลืมทดลองเขียนโค้ดด้วยตัวเองทุกครั้ง อย่าแค่ดูผ่านตา การเจอบั๊ก (Bug - ข้อผิดพลาดในโปรแกรม) จากการพิมพ์ผิดหรือลืมตั้งชื่อตาราง คือบทเรียนที่ดีที่สุด การแก้บั๊กด้วยตัวเองจะทำให้คุณจดจำวิธีเขียนที่ถูกต้องได้แม่นยำกว่าการอ่านตำราเป็นสิบเล่ม

สรุป: การนำไปใช้จริงในโปรเจกต์ของคุณ

สรุปสั้นๆ คือ Self Join มีไว้เพื่อจัดการข้อมูลที่มีความสัมพันธ์กันเองในตารางเดียว ส่วน UNION มีไว้รวมผลลัพธ์จากหลายที่เข้าด้วยกัน การเข้าใจเครื่องมือเหล่านี้จะทำให้คุณจัดการฐานข้อมูลในโปรเจกต์จริงได้ยืดหยุ่นขึ้นมาก โดยเฉพาะเมื่อต้องสร้างระบบที่ซับซ้อน เช่น ระบบจัดการสมาชิก

ตัวอย่างการนำไปใช้จริง: สมมติคุณกำลังทำเว็บไซต์ขายของออนไลน์ คุณอาจมีตาราง categories (หมวดหมู่สินค้า) ที่มีคอลัมน์ parent_id เพื่อบอกว่าหมวดหมู่นี้เป็นลูกของหมวดหมู่ไหน คุณสามารถใช้ Self Join เพื่อดึงชื่อหมวดหมู่หลักและหมวดหมู่ย่อยออกมาแสดงในหน้าเว็บพร้อมกันได้โดยไม่ต้องยิงคำสั่งถามฐานข้อมูลหลายรอบ

ขอให้มองว่าฐานข้อมูลเป็นเหมือนจิ๊กซอว์ การรู้จักคำสั่งเหล่านี้คือการรู้วิธีต่อชิ้นส่วนที่ซับซ้อนให้เข้าที่ ฝึกฝนบ่อยๆ แล้วคุณจะพบว่าการเขียนโค้ดจัดการข้อมูลเป็นเรื่องสนุกและท้าทายความสามารถของคุณในทุกๆ วันที่ได้ลองทำโปรเจกต์ใหม่ๆ

แชร์บทความ

Facebook X LINE

บทความที่เกี่ยวข้อง

MySQL/MariaDB

สอนวิธี Backup และ Restore ฐานข้อมูล MySQL/MariaDB ด้วย mysqldump บน Windows

มือใหม่หัดเขียนโปรแกรมต้องรู้! วิธีสำรองข้อมูล (Backup) และกู้คืน (Restore) ฐานข้อมูลด้วย mysqldump ผ่าน Command Line ป้องกันงานหาย ทำตามได้จริง

1 month ago 9 นาที
23 views
จัดการ User และสิทธิ์ใน MySQL/MariaDB ให้ปลอดภัยด้วยคำสั่ง GRANT และ REVOKE
MySQL/MariaDB

จัดการ User และสิทธิ์ใน MySQL/MariaDB ให้ปลอดภัยด้วยคำสั่ง GRANT และ REVOKE

มือใหม่หัดใช้ฐานข้อมูลต้องรู้! วิธีสร้าง User, กำหนดสิทธิ์ (Permission) และตั้งค่าความปลอดภัยให้ MySQL/MariaDB เพื่อป้องกันข้อมูลรั่วไหลแบบมือโปร

1 month ago 8 นาที
24 views
เข้าใจ MySQL และ MariaDB Trigger: เขียนคำสั่งอัตโนมัติให้ฐานข้อมูลทำงานแทนเรา
MySQL/MariaDB

เข้าใจ MySQL และ MariaDB Trigger: เขียนคำสั่งอัตโนมัติให้ฐานข้อมูลทำงานแทนเรา

อยากให้ฐานข้อมูลทำงานอัตโนมัติเมื่อมีการเพิ่มหรือลบข้อมูลไหม? มาเรียนรู้การใช้ Trigger (ตัวกระตุ้นการทำงาน) ใน MySQL และ MariaDB เพื่อลดภาระงานโค้ดกัน

1 month ago 8 นาที
23 views