อธิบาย MySQL ROW_NUMBER() (MySQL 8.0): การจัดอันดับ, คำสั่ง Top‑N, และการลบข้อมูลซ้ำ

目次

1. บทนำ

MySQL เวอร์ชัน 8.0 ได้นำเสนอคุณลักษณะใหม่หลายอย่าง และหนึ่งในคุณลักษณะที่โดดเด่นคือการสนับสนุนฟังก์ชันหน้าต่าง (window functions) ในบทความนี้ เราจะเน้นไปที่หนึ่งในฟังก์ชันที่ใช้บ่อยที่สุดคือ ROW_NUMBER().

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

กลุ่มผู้อ่านเป้าหมาย

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

ประโยชน์ของ ROW_NUMBER()

ฟังก์ชันนี้ช่วยให้คุณกำหนดหมายเลขที่ไม่ซ้ำกันให้กับแต่ละแถวตามเงื่อนไขที่กำหนด ตัวอย่างเช่น คุณสามารถเขียนคิวรีอย่าง “สร้างการจัดอันดับตามลำดับลดลงของยอดขาย” หรือ “ดึงและจัดระเบียบข้อมูลที่ซ้ำกัน” ได้อย่างกระชับ.

ในเวอร์ชันเก่า คุณมักต้องเขียนคิวรีที่ซับซ้อนโดยใช้ตัวแปรที่กำหนดโดยผู้ใช้ ด้วย ROW_NUMBER() SQL ของคุณจะง่ายขึ้นและอ่านง่ายขึ้น.

ในบทความนี้ เราจะใช้ตัวอย่างคิวรีที่เป็นรูปธรรมและอธิบายอย่างเป็นมิตรต่อผู้เริ่มต้น ในส่วนต่อไป เราจะเจาะลึกไวยากรณ์พื้นฐานและพฤติกรรมของฟังก์ชันนี้.

2. ROW_NUMBER() คืออะไร?

ฟังก์ชัน ROW_NUMBER() ที่เพิ่มเข้ามาใหม่ใน MySQL 8.0 เป็นประเภทของฟังก์ชันหน้าต่างที่กำหนดหมายเลขลำดับให้กับแถว สามารถกำหนดหมายเลขแถวตามลำดับที่ระบุและ/หรือภายในแต่ละกลุ่ม ซึ่งมีประโยชน์อย่างยิ่งสำหรับการวิเคราะห์ข้อมูลและการรายงาน ที่นี่เราจะอธิบายไวยากรณ์พื้นฐานอย่างละเอียดพร้อมตัวอย่างเชิงปฏิบัติ.

ไวยากรณ์พื้นฐานของ ROW_NUMBER()

ก่อนอื่น รูปแบบพื้นฐานของ ROW_NUMBER() มีดังต่อไปนี้.

SELECT
    column_name,
    ROW_NUMBER() OVER (PARTITION BY group_column ORDER BY sort_column) AS row_num
FROM
    table_name;

ความหมายของแต่ละส่วน

  • ROW_NUMBER() : กำหนดหมายเลขลำดับให้กับแต่ละแถว.
  • OVER : คำสำคัญที่ใช้กำหนดหน้าต่างสำหรับฟังก์ชันหน้าต่าง.
  • PARTITION BY : จัดกลุ่มข้อมูลตามคอลัมน์ที่ระบุ เป็นตัวเลือก หากละเว้น การกำหนดหมายเลขจะทำทั่วทั้งแถว.
  • ORDER BY : กำหนดลำดับที่ใช้ในการกำหนดหมายเลข คือเกณฑ์การจัดเรียง.

ตัวอย่างพื้นฐาน

ตัวอย่างเช่น สมมติว่าคุณมีตารางชื่อ “sales” ที่มีข้อมูลดังต่อไปนี้.

employeedepartmentsale
ASales Department500
BSales Department800
CDevelopment Department600
DDevelopment Department700

เพื่อกำหนดหมายเลขลำดับภายในแต่ละแผนกตามลำดับลดลงของยอดขาย ให้ใช้คิวรีต่อนี้.

SELECT
    employee,
    department,
    sale,
    ROW_NUMBER() OVER (PARTITION BY department ORDER BY sale DESC) AS row_num
FROM
    sales;

ผลลัพธ์

employeedepartmentsalerow_num
BSales Department8001
ASales Department5002
DDevelopment Department7001
CDevelopment Department6002

จากผลลัพธ์นี้ คุณจะเห็นว่า การจัดอันดับตามยอดขายภายในแต่ละแผนกถูกแสดงออก.

วิธีใช้ PARTITION BY

ในตัวอย่างข้างต้น ข้อมูลถูกจัดกลุ่มตามคอลัมน์ “department” ซึ่งทำให้แต่ละแผนกมีลำดับแยกกัน.

หากคุณละเว้น PARTITION BY การกำหนดหมายเลขจะทำทั่วทั้งแถวเป็นลำดับเดียว.

SELECT
    employee,
    sale,
    ROW_NUMBER() OVER (ORDER BY sale DESC) AS row_num
FROM
    sales;

ผลลัพธ์

employeesalerow_num
B8001
D7002
C6003
A5004

คุณลักษณะและข้อควรระวังของ ROW_NUMBER()

  • Unique numbering : แม้ค่าจะเท่ากัน หมายเลขที่กำหนดก็ยังเป็นเอกลักษณ์.
  • Handling NULLs : หาก ORDER BY มีค่า NULL จะปรากฏเป็นอันดับแรกในลำดับเพิ่มและเป็นอันดับสุดท้ายในลำดับลด.
  • Performance impact : สำหรับชุดข้อมูลขนาดใหญ่ ORDER BY อาจทำให้ประสิทธิภาพลดลง ดังนั้นการสร้างดัชนีที่เหมาะสมจึงสำคัญ.

3. กรณีการใช้งานจริง

ต่อไปนี้เป็นสถานการณ์การใช้งานจริงของฟังก์ชัน ROW_NUMBER() ของ MySQL ฟังก์ชันนี้มีประโยชน์ในหลายกรณีจริง เช่น การจัดอันดับข้อมูลและการจัดการข้อมูลซ้ำ.

3-1. การจัดอันดับภายในแต่ละกลุ่ม

ตัวอย่างเช่น พิจารณากรณีที่คุณต้องการ “จัดอันดับพนักงานตามยอดขายภายในแต่ละแผนก” โดยใช้ข้อมูลยอดขาย ใช้ชุดข้อมูลต่อไปนี้เป็นตัวอย่าง

employeedepartmentsale
ASales Department500
BSales Department800
CDevelopment Department600
DDevelopment Department700

ตัวอย่างคำสั่ง: การจัดอันดับยอดขายตามแผนก

SELECT
    employee,
    department,
    sale,
    ROW_NUMBER() OVER (PARTITION BY department ORDER BY sale DESC) AS rank
FROM
    sales;

ผลลัพธ์:

employeedepartmentsalerank
BSales Department8001
ASales Department5002
DDevelopment Department7001
CDevelopment Department6002

ในลักษณะนี้ แต่ละแผนกจะได้รับลำดับของตัวเองในลำดับยอดขายจากมากไปน้อย ทำให้ง่ายต่อการสร้างอันดับ

3-2. การดึงแถว Top N

ต่อไป ลองดูกรณีที่คุณต้องการ “ดึงพนักงาน top 3 ตามยอดขายภายในแต่ละแผนก”

ตัวอย่างคำสั่ง: ดึงแถว Top N

WITH RankedSales AS (
    SELECT
        employee,
        department,
        sale,
        ROW_NUMBER() OVER (PARTITION BY department ORDER BY sale DESC) AS rank
    FROM
        sales
)
SELECT
    employee,
    department,
    sale
FROM
    RankedSales
WHERE
    rank <= 3;

ผลลัพธ์:

employeedepartmentsale
BSales Department800
ASales Department500
DDevelopment Department700
CDevelopment Department600

ตัวอย่างนี้จะดึงเฉพาะแถว top 3 ตามยอดขายภายในแต่ละแผนก ดังที่เห็น ROW_NUMBER() ไม่เพียงเหมาะสำหรับการจัดอันดับเท่านั้น แต่ยังเหมาะสำหรับการกรองผลลัพธ์ชั้นนำด้วย

3-3. การค้นหาและลบข้อมูลซ้ำ

ฐานข้อมูลบางครั้งอาจมีเรคคอร์ดซ้ำกัน ในกรณีเช่นนี้ คุณสามารถจัดการได้อย่างง่ายดายโดยใช้ ROW_NUMBER()

ตัวอย่างคำสั่ง: ตรวจจับข้อมูลซ้ำ

SELECT *
FROM (
    SELECT
        employee,
        sale,
        ROW_NUMBER() OVER (PARTITION BY employee ORDER BY sale DESC) AS rank
    FROM
        sales
) tmp
WHERE rank > 1;

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

ตัวอย่างคำสั่ง: ลบข้อมูลซ้ำ

DELETE FROM sales
WHERE id IN (
    SELECT id
    FROM (
        SELECT
            id,
            ROW_NUMBER() OVER (PARTITION BY employee ORDER BY sale DESC) AS rank
        FROM
            sales
    ) tmp
    WHERE rank > 1
);

สรุป

ROW_NUMBER() มีประโยชน์ในสถานการณ์หลากหลาย เช่น:

  1. การจัดอันดับภายในแต่ละกลุ่ม
  2. การดึงแถว Top N
  3. การตรวจจับและลบข้อมูลซ้ำ

สิ่งนี้ทำให้การประมวลผลและวิเคราะห์ข้อมูลที่ซับซ้อนง่ายและมีประสิทธิภาพยิ่งขึ้น

4. การเปรียบเทียบกับ Window Functions อื่นๆ

ใน MySQL 8.0 นอกจาก ROW_NUMBER() แล้ว ยังมี window functions เช่น RANK() และ DENSE_RANK() ที่สามารถใช้สำหรับการจัดอันดับและการคำนวณตำแหน่งได้ แม้ว่าพวกมันจะมีบทบาทคล้ายกัน แต่พฤติกรรมและผลลัพธ์ต่างกัน ที่นี่เราจะเปรียบเทียบแต่ละฟังก์ชันและอธิบายว่าควรใช้เมื่อใด

4-1. ฟังก์ชัน RANK()

ฟังก์ชัน RANK() จะกำหนดอันดับ โดยให้อันดับเดียวกันกับค่าที่เท่ากันและข้ามหมายเลขอันดับถัดไป

ไวยากรณ์พื้นฐาน

SELECT
    column_name,
    RANK() OVER (PARTITION BY group_column ORDER BY sort_column) AS rank
FROM
    table_name;

ตัวอย่าง

โดยใช้ข้อมูลต่อไปนี้ คำนวณอันดับยอดขาย

employeedepartmentsale
ASales Department800
BSales Department800
CSales Department600
DSales Department500

ตัวอย่างคำสั่ง: ใช้ RANK()

SELECT
    employee,
    sale,
    RANK() OVER (ORDER BY sale DESC) AS rank
FROM
    sales;

ผลลัพธ์:

employeesalerank
A8001
B8001
C6003
D5004

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

  • A และ B ที่มียอดขายเท่ากัน (800) จะถูกจัดการเป็นอันดับ “1” ทั้งคู่
  • อันดับถัดไป “2” ถูกข้าม ดังนั้น C จึงกลายเป็นอันดับ “3”

4-2. ฟังก์ชัน DENSE_RANK()

ฟังก์ชัน DENSE_RANK() ก็กำหนดอันดับเดียวกันกับค่าที่เท่ากันเช่นกัน แต่ไม่ข้ามหมายเลขอันดับถัดไป

ไวยากรณ์พื้นฐาน

SELECT
    column_name,
    DENSE_RANK() OVER (PARTITION BY group_column ORDER BY sort_column) AS dense_rank
FROM
    table_name;

ตัวอย่าง

โดยใช้ข้อมูลเดียวกันกับด้านบน ลองใช้ฟังก์ชัน DENSE_RANK()

ตัวอย่างคำสั่ง: ใช้ DENSE_RANK()

SELECT
    employee,
    sale,
    DENSE_RANK() OVER (ORDER BY sale DESC) AS dense_rank
FROM
    sales;

ผลลัพธ์:

employeesaledense_rank
A8001
B8001
C6002
D5003

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

  • A และ B ที่มีจำนวนการขายเท่ากัน (800) จะถูกจัดเป็นอันดับ “1”.
  • แตกต่างจาก RANK() ขั้นต่อไปเริ่มที่ “2” ดังนั้นความต่อเนื่องของอันดับจะถูกเก็บไว้.

4-3. วิธีที่ ROW_NUMBER() แตกต่าง

ฟังก์ชัน ROW_NUMBER() แตกต่างจากสองฟังก์ชันอื่นโดยจะ กำหนดหมายเลขที่ไม่ซ้ำกัน แม้ค่าจะเท่ากัน

ตัวอย่าง

SELECT
    employee,
    sale,
    ROW_NUMBER() OVER (ORDER BY sale DESC) AS row_num
FROM
    sales;

ผลลัพธ์:

employeesalerow_num
A8001
B8002
C6003
D5004

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

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

4-4. สรุปกรณีการใช้งานอย่างรวดเร็ว

FunctionRanking behaviorTypical use case
ROW_NUMBER()Assigns a unique numberWhen you need sequential numbering or unique identification per row
RANK()Same rank for ties; skips the next rank numberWhen you want rankings with gaps reflecting ties
DENSE_RANK()Same rank for ties; does not skip rank numbersWhen you want continuous ranks without gaps

สรุป

ROW_NUMBER(), RANK(), และ DENSE_RANK() ควรใช้ตามความเหมาะสมขึ้นอยู่กับสถานการณ์.

  1. ROW_NUMBER() เหมาะที่สุดเมื่อคุณต้องการหมายเลขที่ไม่ซ้ำกันต่อแถว.
  2. RANK() มีประโยชน์เมื่อคุณต้องการให้ค่าที่เท่ากันแชร์อันดับเดียวกันและต้องการเน้นช่องว่างของอันดับ.
  3. DENSE_RANK() เหมาะเมื่อคุณต้องการอันดับต่อเนื่องโดยไม่มีช่องว่าง.

5. ทางเลือกสำหรับ MySQL เวอร์ชันต่ำกว่า 8.0

ในเวอร์ชันก่อน MySQL 8.0, ROW_NUMBER() และฟังก์ชันหน้าต่างอื่น ๆ ไม่ได้รับการสนับสนุน อย่างไรก็ตาม คุณสามารถทำพฤติกรรมคล้ายกันโดยใช้ตัวแปรที่กำหนดโดยผู้ใช้ ส่วนนี้อธิบายทางเลือกที่ใช้งานได้จริงสำหรับ MySQL เวอร์ชันต่ำกว่า 8.0.

5-1. การกำหนดลำดับเลขต่อเนื่องโดยใช้ตัวแปรที่กำหนดโดยผู้ใช้

ใน MySQL 5.7 และก่อนหน้า คุณสามารถใช้ตัวแปรที่กำหนดโดยผู้ใช้เพื่อกำหนดหมายเลขต่อเนื่องต่อแถว มาดูตัวอย่างต่อไปนี้.

ตัวอย่าง: การจัดอันดับการขายตามแผนก

ข้อมูลตัวอย่าง:

employeedepartmentsale
ASales Department500
BSales Department800
CDevelopment Department600
DDevelopment Department700

คำสั่ง:

SET @row_num = 0;
SET @dept = '';

SELECT
    employee,
    department,
    sale,
    @row_num := IF(@dept = department, @row_num + 1, 1) AS rank,
    @dept := department
FROM
    (SELECT * FROM sales ORDER BY department, sale DESC) AS sorted_sales;

ผลลัพธ์:

employeedepartmentsalerank
BSales Department8001
ASales Department5002
DDevelopment Department7001
CDevelopment Department6002

5-2. การดึงแถว Top N

เพื่อดึงแถว Top N คุณสามารถใช้ตัวแปรที่กำหนดโดยผู้ใช้ในลักษณะเดียวกัน.

คำสั่ง:

SET @row_num = 0;
SET @dept = '';

SELECT *
FROM (
    SELECT
        employee,
        department,
        sale,
        @row_num := IF(@dept = department, @row_num + 1, 1) AS rank,
        @dept := department
    FROM
        (SELECT * FROM sales ORDER BY department, sale DESC) AS sorted_sales
) AS ranked_sales
WHERE rank <= 3;

ผลลัพธ์:

employeedepartmentsalerank
BSales Department8001
ASales Department5002
DDevelopment Department7001
CDevelopment Department6002

คำสั่งนี้กำหนดอันดับตามแผนกและจากนั้นดึงเฉพาะแถวที่อยู่ในอันดับ 3 แรก.

5-3. การตรวจจับและลบข้อมูลซ้ำ

คุณยังสามารถจัดการข้อมูลซ้ำโดยใช้ตัวแปรที่กำหนดโดยผู้ใช้.

ตัวอย่างคำสั่ง: ตรวจจับข้อมูลซ้ำ

SET @row_num = 0;
SET @id_check = '';

SELECT *
FROM (
    SELECT
        id,
        name,
        @row_num := IF(@id_check = name, @row_num + 1, 1) AS rank,
        @id_check := name
    FROM
        (SELECT * FROM customers ORDER BY name, id) AS sorted_customers
) AS tmp
WHERE rank > 1;

ตัวอย่างคำสั่ง: ลบข้อมูลซ้ำ

DELETE FROM customers
WHERE id IN (
    SELECT id
    FROM (
        SELECT
            id,
            @row_num := IF(@id_check = name, @row_num + 1, 1) AS rank,
            @id_check := name
        FROM
            (SELECT * FROM customers ORDER BY name, id) AS sorted_customers
    ) AS tmp
    WHERE rank > 1
);

5-4. ข้อควรระวังเมื่อใช้ตัวแปรที่กำหนดโดยผู้ใช้

  1. การพึ่งพาเซสชัน
  • ตัวแปรที่กำหนดโดยผู้ใช้มีผลเฉพาะภายในเซสชันปัจจุบัน ไม่สามารถนำกลับมาใช้ใหม่ในคำสั่งหรือเซสชันอื่นได้.
  1. การพึ่งพาลำดับการประมวลผล
  • ตัวแปรที่กำหนดโดยผู้ใช้ขึ้นกับลำดับการทำงาน ดังนั้นการกำหนด ORDER BY อย่างเหมาะสมจึงสำคัญ.
  1. ความอ่านง่ายและการบำรุงรักษาของ SQL
  • คำสั่งอาจซับซ้อนขึ้น ดังนั้นใน MySQL 8.0 ขึ้นไป แนะนำให้ใช้ฟังก์ชันหน้าต่าง.

สรุป

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

6. ข้อควรระวังและแนวปฏิบัติที่ดี

ฟังก์ชัน ROW_NUMBER() ของ MySQL และทางเลือกที่ใช้ตัวแปรนั้นสะดวกมาก แต่มีประเด็นสำคัญที่ต้องจำไว้เพื่อให้ทำงานได้อย่างถูกต้องและมีประสิทธิภาพส่วนนี้จะอธิบายข้อควรระวังทางปฏิบัติและแนวปฏิบัติที่ดีที่สุดสำหรับการปรับแต่งประสิทธิภาพ

6-1. ข้อพิจารณาเกี่ยวกับประสิทธิภาพ

1. ต้นทุนของ ORDER BY

ROW_NUMBER() จะถูกใช้เสมอพร้อมกับ ORDER BY เนื่องจากต้องทำการเรียงลำดับ เวลาการประมวลผลจึงอาจเพิ่มขึ้นอย่างมีนัยสำคัญสำหรับชุดข้อมูลขนาดใหญ่

การบรรเทา:

  • ใช้ดัชนี: เพิ่มดัชนีให้กับคอลัมน์ที่ใช้ใน ORDER BY เพื่อเร่งความเร็วในการเรียงลำดับ
  • ใช้ LIMIT: ดึงเฉพาะจำนวนแถวที่ต้องการจริงเพื่อลดปริมาณข้อมูลที่ประมวลผล

ตัวอย่าง:

SELECT
    employee,
    sale,
    ROW_NUMBER() OVER (PARTITION BY department ORDER BY sale DESC) AS rank
FROM
    sales
LIMIT 1000;

2. การใช้งานหน่วยความจำที่เพิ่มขึ้นและ I/O ของดิสก์

ฟังก์ชันหน้าต่างจะถูกประมวลผลโดยใช้ตารางชั่วคราวและหน่วยความจำ เมื่อปริมาณข้อมูลเพิ่มขึ้น การใช้หน่วยความจำและ I/O ของดิสก์ก็จะเพิ่มขึ้น

การบรรเทา:

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

6-2. เคล็ดลับการปรับแต่งคำสั่งค้นหา

1. ตรวจสอบแผนการรัน

ใน MySQL คุณสามารถใช้ EXPLAIN เพื่อตรวจสอบแผนการรันคำสั่งค้นหา สิ่งนี้ช่วยให้คุณยืนยันว่าดัชนีถูกใช้อย่างถูกต้องหรือไม่

ตัวอย่าง:

EXPLAIN
SELECT
    employee,
    ROW_NUMBER() OVER (PARTITION BY department ORDER BY sale DESC) AS rank
FROM
    sales;

ผลลัพธ์ตัวอย่าง:

idselect_typetabletypepossible_keyskeykey_lenrefrowsExtra
1SIMPLEsalesindexNULLsale4NULL500Using index

หากคุณเห็น Using index แสดงว่าดัชนีถูกใช้อย่างเหมาะสม

2. ปรับแต่งดัชนี

โปรดแน่ใจว่าเพิ่มดัชนีให้กับคอลัมน์ที่ใช้ใน ORDER BY และ WHERE ให้ความสนใจเป็นพิเศษกับสิ่งต่อไปนี้

  • ดัชนีคอลัมน์เดียว: ดีสำหรับเงื่อนไขการเรียงลำดับแบบง่าย
  • ดัชนีรวม: มีประสิทธิภาพเมื่อมีคอลัมน์หลายคอลัมน์ที่เกี่ยวข้องกับเงื่อนไข

ตัวอย่าง:

CREATE INDEX idx_department_sale ON sales(department, sale DESC);

3. ใช้การประมวลผลแบบแบทช์

แทนที่จะประมวลผลชุดข้อมูลขนาดใหญ่ทั้งหมดในครั้งเดียว คุณสามารถลดภาระโดยการประมวลผลข้อมูลเป็นแบทช์

ตัวอย่าง:

SELECT * FROM sales WHERE department = 'Sales Department' LIMIT 1000 OFFSET 0;
SELECT * FROM sales WHERE department = 'Sales Department' LIMIT 1000 OFFSET 1000;

6-3. การรักษาความสอดคล้องของข้อมูล

1. การอัปเดตและการคำนวณใหม่

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

ตัวอย่าง:

CREATE VIEW ranked_sales AS
SELECT
    employee,
    sale,
    ROW_NUMBER() OVER (PARTITION BY department ORDER BY sale DESC) AS rank
FROM
    sales;

การใช้มุมมองช่วยให้คุณรักษาการจัดอันดับให้ทันสมัยตามข้อมูลล่าสุด

6-4. ตัวอย่างคำสั่งค้นหาตามแนวปฏิบัติที่ดีที่สุด

ด้านล่างนี้คือตัวอย่างของแนวปฏิบัติที่ดีที่สุดที่พิจารณาประสิทธิภาพและความสามารถในการบำรุงรักษา

ตัวอย่าง: ดึงแถว Top N

WITH RankedSales AS (
    SELECT
        employee,
        department,
        sale,
        ROW_NUMBER() OVER (PARTITION BY department ORDER BY sale DESC) AS rank
    FROM
        sales
)
SELECT *
FROM RankedSales
WHERE rank <= 3;

โครงสร้างนี้ใช้การแสดงออกตารางร่วม (CTE) เพื่อปรับปรุงความสามารถในการอ่านและการนำกลับมาใช้ใหม่

สรุป

เมื่อใช้ ROW_NUMBER() หรือทางเลือกของมัน โปรดจำประเด็นเหล่านี้ไว้:

  1. ปรับปรุงความเร็วด้วย การเพิ่มประสิทธิภาพดัชนี .
  2. ระบุคอขวดโดยตรวจสอบ แผนการดำเนินการ .
  3. วางแผนสำหรับ การอัปเดตข้อมูล และรักษาความสอดคล้อง.
  4. ใช้ การประมวลผลแบบแบตช์ และ CTEs เพื่อกระจายภาระงาน.

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

7. Conclusion

ในบทความนี้ เราได้มุ่งเน้นที่ฟังก์ชัน ROW_NUMBER() ของ MySQL โดยอธิบายทุกอย่างตั้งแต่การใช้งานพื้นฐานและตัวอย่างเชิงปฏิบัติจนถึงทางเลือกสำหรับเวอร์ชันเก่า รวมถึงข้อควรระวังและแนวปฏิบัติที่ดีที่สุด ในส่วนนี้ เราจะสรุปประเด็นสำคัญและสรุปข้อสรุปเชิงปฏิบัติ.

7-1. Why ROW_NUMBER() is useful

ฟังก์ชัน ROW_NUMBER() มีความสะดวกเป็นพิเศษสำหรับการวิเคราะห์และการรายงานข้อมูลในวิธีต่อไปนี้:

  1. การจัดลำดับเลขต่อเนื่องภายในกลุ่ม: สร้างอันดับการขายตามแผนกหรือหมวดหมู่ได้อย่างง่ายดาย.
  2. การดึงแถว Top N: กรองและดึงข้อมูลตามเงื่อนไขเฉพาะอย่างมีประสิทธิภาพ.
  3. การตรวจจับและลบข้อมูลซ้ำ: มีประโยชน์สำหรับการทำความสะอาดและจัดระเบียบข้อมูล.

เนื่องจากมันทำให้คิวรีที่ซับซ้อนง่ายขึ้น จึงปรับปรุงความอ่านง่ายและการบำรุงรักษาของ SQL อย่างมีนัยสำคัญ.

7-2. Comparison with other window functions

เมื่อเทียบกับฟังก์ชันหน้าต่างเช่น RANK() และ DENSE_RANK() ฟังก์ชัน ROW_NUMBER() แตกต่างกันตรงที่มันกำหนดหมายเลขที่ไม่ซ้ำแม้ค่าจะเท่ากัน.

FunctionFeatureUse case
ROW_NUMBER()Assigns a unique sequential number to each rowBest when you need unique identification or ranking with no duplicates
RANK()Same rank for ties; skips the next rank numberWhen you need tie-aware rankings and rank gaps matter
DENSE_RANK()Same rank for ties; does not skip rank numbersWhen you want continuous ranking while handling ties

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

7-3. Handling older MySQL versions

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

  • ความอ่านง่ายลดลงเนื่องจาก SQL ที่ซับซ้อนมากขึ้น
  • การปรับแต่งคิวรีอาจยากขึ้นในบางกรณี
  • อาจต้องมีการจัดการเพิ่มเติมเพื่อรักษาความสอดคล้องของข้อมูล

หากเป็นไปได้ ควรพิจารณาอัปเกรดเป็น MySQL 8.0 หรือใหม่กว่าและใช้ฟังก์ชันหน้าต่าง.

7-4. Key points for performance optimization

  1. ใช้ดัชนี: เพิ่มดัชนีให้กับคอลัมน์ที่ใช้ใน ORDER BY เพื่อปรับปรุงความเร็ว.
  2. ตรวจสอบแผนการดำเนินการ: ตรวจสอบประสิทธิภาพล่วงหน้าด้วย EXPLAIN.
  3. นำการประมวลผลแบบแบตช์มาใช้: ประมวลผลชุดข้อมูลขนาดใหญ่เป็นชิ้นย่อยเพื่อกระจายภาระ.
  4. ใช้วิวและ CTEs: ปรับปรุงการนำกลับมาใช้ใหม่และทำให้คิวรีที่ซับซ้อนง่ายขึ้น.

โดยการใช้เทคนิคเหล่านี้ คุณสามารถบรรลุการประมวลผลข้อมูลที่มีประสิทธิภาพและเสถียร.

7-5. Final notes

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

เราขอแนะนำให้คุณรันคิวรีด้วยตนเองพร้อมกับอ่านบทความนี้ การพัฒนาทักษะ SQL ของคุณจะช่วยให้คุณรับมือกับการวิเคราะห์และการรายงานข้อมูลที่ซับซ้อนมากขึ้นด้วยความมั่นใจ.

Appendix: Reference resources

  • เอกสารอย่างเป็นทางการ: MySQL Window Functions
  • สภาพแวดล้อม SQL ออนไลน์: SQL Fiddle (เครื่องมือที่ให้คุณรันและทดสอบ SQL ออนไลน์)