简体   繁体   中英

Delete equal data from two tables in SQL Server

I have 2 tables with these columns:

Table A

Id | Name  | Salary  
1  | TEST1 | 100  
2  | TEST2 | 200  
3  | TEST3 | 300

Table B

Id | Name  | Salary  
1  | TEST1 | 100  
2  | TEST2 | 200  
4  | TEST4 | 400

I want to delete similar data from two tables (without using joins). When I query

SELECT * 
FROM A 

SELECT * 
FROM B

I should get this result:

Table A

Id | Name  | Salary   
3  | TEST3 | 300

Table B

Id | Name  | Salary   
4  | TEST4 | 400

Any help would be greatly appreciated. Thanks in advance.

PS : I'm going to load the table with around 10 millions rows

Use NOT EXISTS

SELECT * 
FROM   a 
WHERE  NOT EXISTS (SELECT 1 
                   FROM   b 
                   WHERE  a.id = b.id) 

SELECT * 
FROM   b 
WHERE  NOT EXISTS (SELECT 1 
                   FROM   a 
                   WHERE  a.id = b.id) 

For all the field's use EXCEPT

SELECT Id, Name, Salary FROM A
EXCEPT
SELECT Id, Name, Salary FROM B

SELECT Id, Name, Salary FROM B
EXCEPT
SELECT Id, Name, Salary FROM A

To delete the records from tablea use the below query

WITH cte 
     AS (SELECT * 
         FROM   tablea a 
         WHERE  EXISTS (SELECT 1 
                        FROM   tableb b 
                        WHERE  a.id = b.id 
                               AND a.NAME = b.NAME 
                               AND a.salary = b.salary)) 
DELETE FROM cte 

SELECT * 
FROM   tablea 

Before deleting the data from tableA insert the data into temp table to refer when deleting data from tableB

Use DELETE FROM :

SELECT *
INTO #temp
FROM TableA;    -- to get the same data to compare with second DELETE

DELETE t
FROM TableA t
WHERE EXISTS(SELECT Id,Name,Salary
             FROM TableB
             INTERSECT
             SELECT t.ID, t.Name, t.Salary);

DELETE t
FROM TableB t
WHERE EXISTS(SELECT Id,Name,Salary
             FROM #temp
             INTERSECT
             SELECT t.ID, t.Name, t.Salary);  


SELECT * FROM TableA;
SELECT * FROM TableB;

LiveDemo

Output:

 TableA:
╔════╦═══════╦════════╗
║ Id ║ Name  ║ Salary ║
╠════╬═══════╬════════╣
║  3 ║ TEST3 ║    300 ║
╚════╩═══════╩════════╝


TableB:
╔════╦═══════╦════════╗
║ Id ║ Name  ║ Salary ║
╠════╬═══════╬════════╣
║  4 ║ TEST4 ║    400 ║
╚════╩═══════╩════════╝

EDIT:

To avoid coping entire table use OUTPUT clause;

CREATE TABLE #temp(ID INT, NAME VARCHAR(100), Salaray INT);

DELETE t
OUTPUT deleted.Id, deleted.Name, deleted.Salary
INTO #temp
FROM TableA t
WHERE EXISTS(SELECT Id,Name,Salary
             FROM TableB
             INTERSECT
             SELECT t.ID, t.Name, t.Salary);

DELETE t
FROM TableB t
WHERE EXISTS(SELECT Id,Name,Salary 
             FROM (SELECT Id,Name,Salary FROM TableA
                   UNION ALL
                   SELECT Id,Name,Salary FROM #temp) AS sub
             INTERSECT
             SELECT t.ID, t.Name, t.Salary); 

LiveDemo2

To avoid delete problems (log growth, tempdb pressure and so on) you could process data using 100k chunk each. Add WHILE LOOP with 2 variables @range_start, @range_stop and increment by 100k or any other value that suits your system.

You better replace "delete lots of rows" to "create a new table with only those rows remaining" .

Very simple if your SQL Server version supports EXCEPT :

SELECT * INTO newA FROM a
EXCEPT
SELECT * FROM b
;

SELECT * INTO newB FROM b
EXCEPT
SELECT * FROM a
;

See fiddle

EXISTS also simplifies NULL treatment.

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