2016-01-16 4 views
0

у меня есть 2 таблицы с этими столбцами:Удалить одинаковые данные из двух таблиц в SQL Server

Таблица 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: Я собираюсь загрузить таблицу с около 10 миллионов строк

+0

Similiar: только id или все поля? Что, если 'TableB' имеет' 1 TEST1 101'? – lad2025

+1

Должно быть все поля –

+0

@RajuVadnala - Mysql <> Сервер Sql, который вы используете –

ответ

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 лечение.

+0

Создать новый стол очень просто. Но что с ограничениями внешнего ключа/CASDACE DELETE и так далее? – lad2025

+0

@ lad2025: OP хочет: * «сравнить два файла данных. Размер файла может составлять около 3 ГБ, имея записи более 10 миллионов. Мне нужно загрузить файл в таблицы и удалить похожие данные» * – dnoeth

+0

И OP предоставлен очень упрощенный версия с 3 фиктивными столбцами. И как вы узнаете, что коэффициент удаления составит 95%, а не 5%? – lad2025

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

+0

Почему только на основе 'id'? И не целая строка? – lad2025

+0

@ lad2025 - обновлен. –

+0

Я сравниваю полные данные строки, а не первичный ключ. В идеале все столбцы должны быть объединены, так как у меня много столбцов для моей таблицы, я собираюсь избегать объединений. –

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 ║ 
╚════╩═══════╩════════╝ 

EDIT:

Чтобы избежать справляясь Целой таблицей использования 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 и приращением на 100 тыс. Или любым другим значением, которое подходит вашей системе.

+0

Это действительно здорово, спасибо, но как насчет удаления таких же данных из B? –

+0

Да, это выглядит хорошо, но я хочу загрузить таблицы с 10 миллионами строк. Будет ли звучать хорошо, чтобы загрузить это в другую таблицу, чтобы сделать удаление? –

+0

Да, но что, если данные удаляются миллионами? На самом деле мне нужно сравнить два файла данных. размер файла может составлять около 3 ГБ, имея записи более 10 миллионов. Мне нужно загрузить файл в таблицы и удалить похожие данные. –

Смежные вопросы