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;
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);
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.