sql >> Database teknologi >  >> RDS >> Mysql

Hvordan vælger og/eller sletter man alle på nær én række af hvert sæt dubletter i en tabel?

Her er en løsning. Jeg testede dette på MySQL 5.5.8.

SELECT MAX(COALESCE(c2.id, c1.id)) AS id, c1.driver_id, c1.car_id, c2.notes AS notes FROM cars_drivers AS c1 LEFT OUTER JOIN cars_drivers AS c2 ON (c1.driver_id,c1.car_id) = (c2.driver_id,c2.car_id) AND c2.notes IS NOT NULL GROUP BY c1.driver_id, c1.car_id, c2.notes;

Jeg inkluderer c2.notes som en GROUP BY-nøgle, fordi du måske har mere end én række med ikke-null-noter pr. værdier af driver_id,car_id.

Resultat ved hjælp af dine eksempeldata:

+------+-----------+--------+-------+ | id | driver_id | car_id | notes | +------+-----------+--------+-------+ | 2 | 1 | 1 | NULL | | 4 | 2 | 1 | NULL | | 8 | 3 | 2 | hi | | 9 | 5 | 3 | NULL | +------+-----------+--------+-------+

Angående sletning. I dine eksempeldata er det altid den højeste id-værdi pr. driver_id &car_id, som du vil beholde. Hvis du kan stole på det, kan du foretage en multi-table sletning, der sletter alle rækker, for hvilke der findes en række med en højere id-værdi og samme driver_id &car_id:

DELETE c1 FROM cars_drivers AS c1 INNER JOIN cars_drivers AS c2
 ON (c1.driver_id,c1.car_id) = (c2.driver_id,c2.car_id) AND c1.id < c2.id;
 

Dette springer naturligvis alle tilfælde over, hvor der kun eksisterer én række med et givet par af driver_id &car_id værdier, fordi betingelserne for den indre join kræver to rækker med forskellige id værdier.

Men hvis du ikke kan stole på, at det seneste id pr. gruppe er det, du vil beholde, er løsningen mere kompleks. Det er sandsynligvis mere komplekst, end det er værd at løse i én sætning, så gør det i to sætninger.

Jeg testede også dette efter at have tilføjet et par rækker mere til test:

INSERT INTO cars_drivers VALUES (10,2,3,NULL), (11,2,3,'bye');

+----+--------+-----------+-------+
| id | car_id | driver_id | notes |
+----+--------+-----------+-------+
|  1 |      1 |         1 | NULL  |
|  2 |      1 |         1 | NULL  |
|  3 |      1 |         2 | NULL  |
|  4 |      1 |         2 | NULL  |
|  5 |      2 |         3 | NULL  |
|  6 |      2 |         3 | NULL  |
|  7 |      2 |         3 | NULL  |
|  8 |      2 |         3 | hi    |
|  9 |      3 |         5 | NULL  |
| 10 |      2 |         3 | NULL  |
| 11 |      2 |         3 | bye   |
+----+--------+-----------+-------+
 

Slet først rækker med nul-noter, hvor der findes en række med ikke-nul-noter.

DELETE c1 FROM cars_drivers AS c1 INNER JOIN cars_drivers AS c2
 ON (c1.driver_id,c1.car_id) = (c2.driver_id,c2.car_id)
WHERE c1.notes IS NULL AND c2.notes IS NOT NULL;

+----+--------+-----------+-------+
| id | car_id | driver_id | notes |
+----+--------+-----------+-------+
|  1 |      1 |         1 | NULL  |
|  2 |      1 |         1 | NULL  |
|  3 |      1 |         2 | NULL  |
|  4 |      1 |         2 | NULL  |
|  8 |      2 |         3 | hi    |
|  9 |      3 |         5 | NULL  |
| 11 |      2 |         3 | bye   |
+----+--------+-----------+-------+
 

For det andet skal du slette alle undtagen rækken med højeste id fra hver gruppe af dubletter.

DELETE c1 FROM cars_drivers AS c1 INNER JOIN cars_drivers AS c2
 ON (c1.driver_id,c1.car_id) = (c2.driver_id,c2.car_id) AND c1.id < c2.id;

+----+--------+-----------+-------+
| id | car_id | driver_id | notes |
+----+--------+-----------+-------+
|  2 |      1 |         1 | NULL  |
|  4 |      1 |         2 | NULL  |
|  9 |      3 |         5 | NULL  |
| 11 |      2 |         3 | bye   |
+----+--------+-----------+-------+
 


  1. Forskellen mellem Oracle jdbc driver klasser?

  2. Tilføj år til en dato i PostgreSQL

  3. Vil du slette alle poster undtagen den seneste?

  4. UTF8 MySQL-problemer på skinner - kodningsproblemer med utf8_general_ci