Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> MySQL

ลบข้อมูลซ้ำเพียง 1 แถวด้วย DELETE ... LIMIT ใน MySQL


สถานการณ์

ตารางมีข้อมูลซ้ำหลายแถว (เช่น Amount = 50 ซ้ำ 3 ครั้ง) ต้องการลบแค่ 1 แถว ไม่ใช่ลบทั้งหมด

วิธีแก้: ใช้ DELETE ... LIMIT 1

DELETE FROM table WHERE condition LIMIT 1; จำกัดการลบไม่เกิน 1 แถว

ตัวอย่างการใช้งาน

1. สร้างตาราง

mysql> CREATE TABLE DemoTable (
    -> Amount INT
    -> );
Query OK, 0 rows affected (1.38 sec)

2. เพิ่มข้อมูล (50 ซ้ำ 3 ครั้ง)

mysql> INSERT INTO DemoTable VALUES(50);
Query OK, 1 row affected (0.23 sec)
mysql> INSERT INTO DemoTable VALUES(100);
Query OK, 1 row affected (0.36 sec)
mysql> INSERT INTO DemoTable VALUES(50);
Query OK, 1 row affected (0.59 sec)
mysql> INSERT INTO DemoTable VALUES(70);
Query OK, 1 row affected (0.18 sec)
mysql> INSERT INTO DemoTable VALUES(90);
Query OK, 1 row affected (0.13 sec)
mysql> INSERT INTO DemoTable VALUES(50);
Query OK, 1 row affected (0.23 sec)

3. แสดงข้อมูลก่อนลบ

mysql> SELECT * FROM DemoTable;

ผลลัพธ์:

+--------+
| Amount |
+--------+
| 50     |
| 100    |
| 50     |
| 70     |
| 90     |
| 50     |
+--------+
6 rows in set (0.00 sec)

4. ลบ Amount = 50 แค่ 1 แถว

mysql> DELETE FROM DemoTable WHERE Amount = 50 LIMIT 1;
Query OK, 1 row affected (0.39 sec)

5. ตรวจสอบหลังลบ

mysql> SELECT * FROM DemoTable;

ผลลัพธ์ (เหลือ 50 อีก 2 แถว):

+--------+
| Amount |
+--------+
| 100    |
| 50     |
| 70     |
| 90     |
| 50     |
+--------+
5 rows in set (0.00 sec)

ข้อควรระวัง

  • ไม่มี ORDER BY ใน DELETE → ไม่สามารถควบคุมได้ว่า "แถวไหน" จะถูกลบ (MySQL เลือกเอง)
  • หากต้องการลบแถวเฉพาะ ให้ใช้ Primary Key: DELETE FROM DemoTable WHERE Id = 123 LIMIT 1;
  • LIMIT ใน DELETE เป็น MySQL Extension (ไม่ใช่ Standard SQL)

วิธีลบแถวเฉพาะเจาะจง (Best Practice)

1. ใช้ Primary Key

DELETE FROM DemoTable WHERE Id = (SELECT Id FROM DemoTable WHERE Amount = 50 ORDER BY Id LIMIT 1);

2. ใช้ JOIN กับ Subquery

DELETE d FROM DemoTable d
JOIN (SELECT Id FROM DemoTable WHERE Amount = 50 ORDER BY Id LIMIT 1) t
ON d.Id = t.Id;

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

  • ลบ Log เก่า ทีละ Batch (LIMIT 1000) เพื่อไม่ Lock ตารางนาน
  • Cleanup Duplicate: ลบทีละ 1 จนกว่าจะไม่ซ้ำ
  • Soft Delete Simulation: ย้ายแทนลบ (INSERT INTO archive SELECT ... LIMIT 1; DELETE ... LIMIT 1;)

ลบ Duplicate ทั้งหมดเก็บแค่ 1 แถว

-- MySQL 8.0+ ใช้ ROW_NUMBER()
WITH cte AS (
    SELECT Id, ROW_NUMBER() OVER (PARTITION BY Amount ORDER BY Id) AS rn
    FROM DemoTable
)
DELETE FROM DemoTable WHERE Id IN (SELECT Id FROM cte WHERE rn > 1);