简体   繁体   中英

Deleting table entries based on criteria in another table

We want to be able to delete entries from a MySQL table, based on deletion criteria set in another table. Let me explain with an example.
I have two tables defined as follows:

CREATE TABLE base_tbl
(
  id INT UNSIGNED NOT NULL AUTO_INCREMENT,
  f1 VARCHAR(8),
  f2 VARCHAR(8),
  
  PRIMARY KEY (id)
);


CREATE TABLE del_criteria_tbl
(
  id INT UNSIGNED NOT NULL AUTO_INCREMENT,
  f3 VARCHAR(8),
  f4 VARCHAR(8),
  
  PRIMARY KEY (id)
);

base_tbl has the data and del_criteria_tbl has the criteria for deleting entries from base_tbl .

I populate the tables as follows:

INSERT INTO base_tbl(f1, f2) VALUES ('ABC', '123C57'),
('ABC', '532B49'), ('DEF', '397F45'),
('DEF', '684G65'), ('GHI', '793A86'),
('GHI', '541H32');  

and

INSERT INTO del_criteria_tbl(f3, f4) VALUES ('ABC', '532B49'),
('ABC', '813E89'), ('DEF', '397F45'),
('GHI', '541H32');

Obviously:

mysql>SELECT * FROM base_tbl;
+----+------+--------+
| id | f1   | f2     |
+----+------+--------+
|  1 | ABC  | 123C57 |
|  2 | ABC  | 532B49 |
|  3 | DEF  | 397F45 |
|  4 | DEF  | 684G65 |
|  5 | GHI  | 793A86 |
|  6 | GHI  | 541H32 |
+----+------+--------+


mysql>SELECT * FROM del_criteria_tbl;
+----+------+--------+
| id | f3   | f4     |
+----+------+--------+
|  1 | ABC  | 532B49 |
|  2 | ABC  | 813E89 |
|  3 | DEF  | 397F45 |
|  4 | GHI  | 541H32 |
+----+------+--------+

I would like to define a succinct and efficient SQL operation that executes the following pseudo-SQL logic:

DELETE FROM base_tbl WHERE base_tbl.f1 = del_criteria_tbl.f3 AND base_tbl.f2 = del_criteria_tbl.f4

After the operation is executed, SELECT * FROM base_tbl should yield:

+----+------+--------+
| id | f1   | f2     |
+----+------+--------+
|  1 | ABC  | 123C57 |
|  4 | DEF  | 684G65 |
|  5 | GHI  | 793A86 |
+----+------+--------+

A simple method is IN :

DELETE b FROM base_tbl b
    WHERE (b.f1, b.f2) IN (SELECT dc.f3, dc.f4
                           FROM del_criteria_tbl dc
                          );

With indexes on (f1, f2) , you might find a JOIN has better performance:

DELETE b
    FROM base_tbl b JOIN
         del_criteria_tbl dc
         ON b.f1 = dc.f3 AND b.f2 = c.f4;

I would recommend exists :

delete b
from base_tbl b
where exists (
    select 1
    from del_criteria_tbl dc
    where dc.f1 = b.f1 and dc.f2 = b.f2
)

This seems like the most natural way to phrase what you ask for. exists usually scales better than in over large datasets. For performance, you want an index on del_criteria_tbl(f1, f2) .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM