2013-11-06 3 views
2

Давайте рассмотрим, что у меня есть таблица A, которую я использую для создания таблицы B. У меня нет первичного ключа или уникального ключа, который я мог бы использовать для ON DUPLICATE KEY.SQL INSERT без дубликата (нет первичных или уникальных ключей)

Моя таблица B имеет 3 колонки: A, B и C.

Я хочу INSERT этого только если строка уже не существует. Я могу определить, существует ли строка в комбинации A и B. Для этого я использую оператор WHERE NOT EXISTS.

INSERT INTO TableB 
(A, B, C) 
SELECT 
SUM(A), 
SUM(B), 
SUM(C) 
FROM TableA 
WHERE NOT EXISTS (SELECT * FROM TABLE B WHERE A=A AND B=B) 
GROUP BY A, B 

Если в таблице B пусто, то строка вставляется. Однако, как только таблица B имеет запись, ни одна строка не вставлена, даже если они уже не существуют в таблице B.

+0

Почему бы не использовать 'UNIQUE (A, B, C)'? – Fozi

+1

@Fozi Потому что А можно повторить. B также можно повторить, но это единственная комбинация из двух уникальных. Это характер данных, с которыми я работаю. – Wistar

+0

Ant это именно то, что «UNIQUE (A, B, C)» сделает для вас; Это не то же самое, что «УНИКАЛЬНЫЙ (A) УНИКАЛЬНЫЙ (B) УНИКАЛЬНЫЙ (C)». – Fozi

ответ

1

Я думаю, что лучше и быстрее способ сделать это, чтобы применить UNIQUE ограничение на + B.

Alter TABLE TableB ADD CONSTRAINT unique_A_B UNIQUE(A,B); 

Затем используйте ON DUPLICATE KEY UPDATE:

INSERT INTO TableB (A,B,C) 
SELECT 
     SUM(A), 
     SUM(B), 
     SUM(C) 
    FROM TableA 
GROUP BY A, B 
ON DUPLICATE KEY UPDATE C=SUM(C); 

Для примера цели Я обновил C, но я предполагаю, что в реальной ситуации вам нужно обновить временную метку обновления вашей строки с помощью Now().

5

Вы должны префиксом столбцы из внешнего запроса с его псевдонима в подзапрос:

INSERT INTO TableB (A, B, C) 
    SELECT 
     SUM(A), 
     SUM(B), 
     SUM(C) 
    FROM TableA ta 
    WHERE NOT EXISTS (SELECT * FROM TableB tb WHERE tb.A=ta.A AND tb.B=ta.B) 
    GROUP BY A, B 

Как вы его написали, вы сравнивали значения из таблицы TableB со значениями от TableB (каждая строка сама по себе), поэтому, когда вы вставили хотя бы одну строку, условие, что «нет строки, которая равна самому себе «никогда не было правдой.

+0

Однако это значительно увеличило время выполнения моего запроса (от примерно 0,1 до 10 секунд) – Wistar

+1

@Wistar Конечно! В вашей версии, когда в 'TableB' была хотя бы одна строка, условие« НЕ СУЩЕСТВУЕТ »никогда не выполнялось, и для того, чтобы это условие завершилось, потребовалось только одна запись из« TableB ». Когда вы изменили его для правильной работы (проверьте значения из таблицы из внешнего запроса), он должен проверить все строки и посмотреть, не имеют ли они ни одного из этих значений - он должен быть медленнее (было бы неплохо иметь составной индекс в 'TableB. A' и 'TableB.B'). –

+0

Как предположил @Fozi, возможно, использование ограничения UNIQUE (A, B) 'в таблице B, а затем использование' ON DUPLICATE KEY UPDATE' может быть более эффективным. – Wistar

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