0Pricing
SQL Interview Prep · บทเรียน

เปรียบเทียบแถวภายในตารางเดียวกัน

รูปแบบการเชื่อมตารางเข้ากับตัวเองสำหรับค้นหาคู่ข้อมูล ข้อมูลซ้ำ และระเบียนที่อยู่ติดกัน

เปรียบเทียบแถวภายในตารางเดียวกัน เป็นบทเรียน SQL Interview Prep ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน SQL Interview Prep และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส SQL Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน

การเชื่อมตารางกับตัวเองเพื่อเปรียบเทียบแถวต่อแถว

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

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

การค้นหาคู่ในกลุ่มเดียวกัน

คำถามคลาสสิกคือ ค้นหาคู่พนักงานทั้งหมดที่ทำงานอยู่ในแผนกเดียวกัน ให้เชื่อมตารางเข้ากับตัวเองโดยใช้แผนกที่เท่ากัน แต่ต้องเก็บแถวทั้งสองให้แยกจากกัน

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

SELECT a.name, b.name, a.department
FROM employees a
JOIN employees b ON a.department = b.department;

การตัดคู่ที่จับคู่กับตัวเองและรายการซ้ำแบบกลับด้าน

การจับคู่สมาชิกในกลุ่มเดียวกันมีปัญหาสองประการ คือแถวหนึ่งจับคู่กับตัวเอง เช่น อลิซกับอลิซ และแต่ละคู่ปรากฏสองครั้ง เช่น อลิซ-บ็อบและบ็อบ-อลิซ

แก้ทั้งสองปัญหาด้วยเงื่อนไขไม่เท่ากันเพียงข้อเดียว: a.id < b.id วิธีนี้รับประกันว่าแถวทั้งสองแตกต่างกันและเก็บลำดับของแต่ละคู่ไว้เพียงแบบเดียว

SELECT a.name, b.name, a.department
FROM employees a
JOIN employees b
  ON a.department = b.department
 AND a.id < b.id;

เหตุใดจึงใช้ a.id < b.id ไม่ใช่ a.id <> b.id

การใช้ a.id <> b.id จะตัดคู่ที่จับคู่กับตัวเองออก แต่ยังคงส่งคืนทั้งสองลำดับ ทำให้ผลลัพธ์เพิ่มเป็นสองเท่า การใช้ a.id < b.id จะตัดคู่ที่จับคู่กับตัวเองออกและลบรายการซ้ำแบบกลับด้านได้ในครั้งเดียว

ผู้สัมภาษณ์จะสังเกตเป็นพิเศษว่าคุณเลือก < หรือ <> เพราะแสดงให้เห็นว่าคุณเข้าใจหลักการจัดชุดของการเชื่อมตารางกับตัวเอง

-- <>  keeps Alice-Bob AND Bob-Alice (duplicated)
-- <   keeps only Alice-Bob (correct unique pairs)

การค้นหาแถวซ้ำ

หากต้องการค้นหาระเบียนที่ซ้ำกันโดยพิจารณาจากคอลัมน์คีย์ ให้เชื่อมตารางกับตัวเองโดยใช้คอลัมน์เหล่านั้น และกำหนดให้คีย์หลักแตกต่างกัน

ที่นี่ เราแสดงลูกค้าที่ใช้อีเมลเดียวกัน เงื่อนไข a.id < b.id ทำให้แต่ละคู่ซ้ำปรากฏเพียงครั้งเดียว โดยทั่วไป GROUP BY ... HAVING COUNT(*) > 1 อาจอ่านง่ายกว่า แต่การเชื่อมตารางกับตัวเองจะแสดงคู่ที่มีปัญหาจริงให้เห็นเคียงข้างกัน

SELECT a.id, b.id, a.email
FROM customers a
JOIN customers b
  ON a.email = b.email
 AND a.id < b.id;

การเปรียบเทียบระเบียนที่อยู่ติดกัน

งานที่นักวิเคราะห์ทำบ่อยคือเปรียบเทียบแต่ละแถวกับแถวถัดไปตามลำดับ เช่น เปรียบเทียบยอดขายของแต่ละวันกับวันก่อนหน้า การเชื่อมตารางกับตัวเองสามารถจับคู่แถวที่อยู่ต่อเนื่องกันได้

ที่นี่ เราเชื่อมแต่ละวันกับแถวของวันที่ก่อนหน้าหนึ่งวันพอดีเพื่อคำนวณค่าความแตกต่าง วิธีนี้ใช้ได้เมื่อในลำดับไม่มีช่องว่าง

SELECT t.day, t.amount,
       t.amount - y.amount AS change_vs_prev
FROM daily_sales t
JOIN daily_sales y
  ON y.day = t.day - INTERVAL '1 day';

ปัญหาช่องว่างของการเชื่อมตารางกับตัวเองแบบแถวติดกัน

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

นี่คือเหตุผลที่ผู้สัมภาษณ์มักแนะนำให้ใช้ฟังก์ชันหน้าต่างอย่าง LAG สำหรับการ 'เปรียบเทียบกับแถวก่อนหน้า' ซึ่งใช้ตำแหน่งตามลำดับแทนการจับคู่ค่า และรองรับช่องว่างได้อย่างราบรื่น

-- LAG handles gaps; the self join assumed contiguous days
SELECT day, amount,
       amount - LAG(amount) OVER (ORDER BY day) AS change_vs_prev
FROM daily_sales;

การเชื่อมตารางกับตัวเองเทียบกับฟังก์ชันหน้าต่าง

โปรดทำความเข้าใจข้อแลกเปลี่ยน:

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

หากต้องการ ‘เปรียบเทียบกับแถวข้างเคียง’ ควรใช้ LAG/LEAD หากต้องการ ‘ค้นหาคู่ทั้งหมดที่ตรงตามเงื่อนไข’ การเชื่อมตารางกับตัวเองเป็นเครื่องมือที่เหมาะสมที่สุด

การค้นหาแถวที่มีค่ามากกว่าแถวร่วมกลุ่ม

อีกหนึ่งรูปแบบคือการค้นหาพนักงานที่มีรายได้มากกว่าเพื่อนร่วมงานอย่างน้อยหนึ่งคนในแผนกเดียวกัน การเชื่อมตารางกับตัวเองช่วยแสดงเงื่อนไขนี้ได้โดยตรง

เราเชื่อมพนักงานแต่ละคนกับพนักงานคนอื่นในแผนกเดียวกันซึ่งมีรายได้น้อยกว่า จากนั้นเลือกเฉพาะพนักงานที่ไม่ซ้ำกันซึ่งปรากฏอยู่ ผลลัพธ์นี้อ่านได้แทบจะเหมือนประโยคภาษาอังกฤษ

SELECT DISTINCT a.name, a.department, a.salary
FROM employees a
JOIN employees b
  ON a.department = b.department
 AND a.salary > b.salary;

ระวังการเพิ่มจำนวนแถว

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

โปรดใส่เงื่อนไขสำหรับกำจัดรายการซ้ำเสมอ (a.id < b.id) และเพิ่ม DISTINCT หรือการจัดกลุ่มเมื่อคุณต้องการเพียงแถวที่มีส่วนร่วม ไม่ใช่คู่ทั้งหมด โปรดตระหนักถึงการเพิ่มจำนวนแถวลักษณะนี้เมื่อตอบคำถามสัมภาษณ์

การเลือกเครื่องมือสำหรับเปรียบเทียบ

แนวทางตัดสินใจสำหรับการเปรียบเทียบข้อมูลภายในตารางเดียวกัน:

  • คู่ที่ตรงกันทั้งหมด คู่ (รายการซ้ำหรือการจับคู่ภายในกลุ่มเดียวกัน): การเชื่อมตารางกับตัวเองด้วย a.id < b.id
  • แถวก่อนหน้าหรือถัดไปตามลำดับ: ฟังก์ชันหน้าต่าง (LAG/LEAD)
  • เปรียบเทียบแต่ละแถวกับค่ารวมของกลุ่ม: คิวรีย่อยที่สัมพันธ์กันหรือฟังก์ชันรวมแบบหน้าต่าง

ตรวจสอบอย่างรวดเร็ว

คุณต้องการคู่ผลิตภัณฑ์ที่ไม่ซ้ำกันทุกคู่ซึ่งอยู่ในหมวดหมู่เดียวกัน โดยห้ามจับคู่ผลิตภัณฑ์กับตัวเองและห้ามมีลำดับคู่ที่ซ้ำกัน

ทบทวน: การเปรียบเทียบแถวภายในตารางเดียวกัน

ประเด็นสำคัญ:

  • เชื่อมตารางกับตัวเองเพื่อจับคู่แถวภายในตารางเดียวกัน สำหรับค้นหารายการซ้ำและการจับคู่ภายในกลุ่มเดียวกัน
  • ใช้ a.id < b.id เพื่อตัดคู่ที่จับแถวกับตัวเองและคู่ซ้ำที่กลับลำดับออกด้วยเงื่อนไขเดียว
  • การเปรียบเทียบแถวข้างเคียงด้วยการเชื่อมตารางกับตัวเองจะทำงานผิดพลาดเมื่อมีช่วงขาดหาย ควรใช้ LAG/LEAD สำหรับตรรกะที่เกี่ยวกับแถวก่อนหน้าหรือถัดไป
  • โปรดคำนึงถึงการเพิ่มจำนวนแถวเสมอเมื่อเชื่อมตารางด้วยคอลัมน์ที่มีค่าซ้ำกันไม่ได้

คำถามที่พบบ่อย

บทเรียน “เปรียบเทียบแถวภายในตารางเดียวกัน” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “เปรียบเทียบแถวภายในตารางเดียวกัน” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส SQL Interview Prep ให้อัปเกรดเป็น CoddyKit PRO คอร์ส SQL Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “เปรียบเทียบแถวภายในตารางเดียวกัน”

รูปแบบการเชื่อมตารางเข้ากับตัวเองสำหรับค้นหาคู่ข้อมูล ข้อมูลซ้ำ และระเบียนที่อยู่ติดกัน คุณปฏิบัติ SQL Interview Prep ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน SQL Interview Prep หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน SQL Interview Prep บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน

บทเรียน “เปรียบเทียบแถวภายในตารางเดียวกัน” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน SQL Interview Prep นี้ได้ไหม

ได้ บทเรียน SQL Interview Prep ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. CROSS JOIN และผลคูณคาร์ทีเซียน
  2. SELF JOIN สำหรับโครงสร้างลำดับชั้น
  3. เปรียบเทียบแถวภายในตารางเดียวกัน
  4. เลือกประเภทการเชื่อมตารางที่เหมาะสม
← กลับไปที่ SQL Interview Prep