简体   繁体   English

从SQL Server中的两个表中删除相等的数据

[英]Delete equal data from two tables in SQL Server

I have 2 tables with these columns: 我有两列这些表:

Table A 表A

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

Table B 表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 表A

Id | Name  | Salary   
3  | TEST3 | 300

Table B 表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 PS:我将向该表加载约1000万行

Use NOT EXISTS 使用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 对于所有领域,请使用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 要从tablea删除记录,请使用以下查询

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 从删除数据之前tableA将数据插入到临时表从删除数据时,参考tableB

Use DELETE FROM : 使用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; 为了避免处理整个表,请使用OUTPUT子句;

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. 为了避免删除问题(日志增长,tempdb压力等),您可以每个使用100k块来处理数据。 Add WHILE LOOP with 2 variables @range_start, @range_stop and increment by 100k or any other value that suits your system. 使用2个变量@range_start, @range_stop添加WHILE LOOP @range_start, @range_stop并递增100k或其他适合您系统的值。

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 : 如果您的SQL Server版本支持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. EXISTS还简化了NULL处理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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