我有两个包含这些列的表:
表A
Id | Name | Salary
1 | TEST1 | 100
2 | TEST2 | 200
3 | TEST3 | 300
表B
Id | Name | Salary
1 | TEST1 | 100
2 | TEST2 | 200
4 | TEST4 | 400
我想从两个表中删除类似的数据(不使用连接)。当我查询
SELECT *
FROM A
SELECT *
FROM B
我应该得到这个结果:
表A
Id | Name | Salary
3 | TEST3 | 300
表B
Id | Name | Salary
4 | TEST4 | 400
非常感谢任何帮助。提前谢谢。
PS:我要加载约1000万行的表格
答案 0 :(得分:3)
使用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)
对于所有字段的使用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
要从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
从tableA
删除数据之前,将数据插入临时表,以便在从tableB
删除数据时引用
答案 1 :(得分:1)
使用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
强>
输出:
TableA:
╔════╦═══════╦════════╗
║ Id ║ Name ║ Salary ║
╠════╬═══════╬════════╣
║ 3 ║ TEST3 ║ 300 ║
╚════╩═══════╩════════╝
TableB:
╔════╦═══════╦════════╗
║ Id ║ Name ║ Salary ║
╠════╬═══════╬════════╣
║ 4 ║ TEST4 ║ 400 ║
╚════╩═══════╩════════╝
修改强>
为避免复制整个表格,请使用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
强>
为避免删除问题(日志增长,tempdb压力等),您可以使用每个100k块处理数据。添加WHILE LOOP
包含2个变量@range_start, @range_stop
并增加100k或任何其他适合您系统的值。
答案 2 :(得分:0)
您最好将“删除大量行”替换为“创建只包含剩余行的新表。
如果您的SQL Server版本支持EXCEPT
,则非常简单:
SELECT * INTO newA FROM a
EXCEPT
SELECT * FROM b
;
SELECT * INTO newB FROM b
EXCEPT
SELECT * FROM a
;
请参阅fiddle
EXISTS
也简化了NULL
治疗。