![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Удаление данных из таблицы с подзапросом [MSSQL]
Ольга © (2006-08-21 17:42:00)Не могу составить правильный запрос на удаление. Делаю выборку данных, которые хочу удалить:
SELECT * FROM T1 a
WHERE NOT EXISTS (select id1, id2 from T2 b where a.id1=b.id1 and a.id2=b.id2)
Выбирается, то, что надо. Беру подзапрос в скобки, добавляю в начало:
DELETE FROM T1 WHERE EXISTS (подзапрос)
Получаю полное удаление всех записей.
Делаю какую-то глупость и не вижу где. Помогайте, мастера.
Dok (2006-08-23 10:40:00) [1]
> На самом деле, ошибка в where T1.FirstKeyField is null -
> должно быть where T2.FirstKeyField is null
ну правильно. или правое соединение:)
> > left outer join будет медленее чем exists
> Сравни планы.
Только что проверил на 80 тыс. в T1 и 600 тыс в T2 Выиграл exists. Это и понятно судя из того как работает внешнее соединение и как exists.
Индексы по полям соединения есть.
Fay (2006-08-22 19:45:00) [2]Dok (22.08.06 18:43) [17]
> потому что нужно выбрать те которых нет в T2
На самом деле, ошибка вwhere T1.FirstKeyField is null- должно бытьwhere T 2.FirstKeyField is null
P.S.
> left outer join будет медленее чем exists
Сравни планы.
Dok (2006-08-22 18:43:00) [3]потому что нужно выбрать те которых нет в T2
Fay (2006-08-22 17:21:00) [4]Dok (22.08.06 10:55) [15]
Почему правое?
Dok (2006-08-22 10:55:00) [5]
> не можете, так как левое соединение даст null для тех записей
> которых нет в T1, что Вам и требовалось.
вообще-то тут нужно правое соединение
Ольга (2006-08-22 10:14:00) [6]Разобралась что почем.
Всем спасибо!
Dok (2006-08-22 10:07:00) [7]
> В данных условиях я могу обойтись без этого where или я
> чего-то недопоняла?
не можете, так как левое соединение даст null для тех записей которых нет в T1, что Вам и требовалось.
Dok (2006-08-22 10:03:00) [8]
> from T1 left join T2 on T1.ID1 = T2.ID1 and T1.ID2 = T2.
> ID2
left outer join будет медленее чем exists
Ольга (2006-08-22 09:31:00) [9]Можно еще раз пояснить (для "особо сообразительных").
Подробнее:
Т1 - некая таблица, на которую планируется наложить внешний ключ
Т1.id1, Т1.id2 - поля, соответствующие первичному ключу внешней таблицы
Т2 - внешняя таблица
Т2.id1, Т2.id2 - первичный ключ
В полях Т1.id1, Т1.id2 может попасться null, как частный случай.
В данных условиях я могу обойтись без этого where или я чего-то недопоняла?
sniknik (2006-08-22 09:01:00) [10]> Это условие зачем?
отбирает для удаления только "неподсоеденившиеся концы" в обьеденении, т.е. по смыслу - то чего нет в другой таблице (NOT EXISTS по смыслу).
> И что за зверь FirstKeyField?
дикий...
т.к. в вопросе не приведена структура таблиц/используемые поля (но из запросов ясно что id1, id2 скорее всего не ключевые, иначе хватило бы одного сравнения), то тебе дали свой вариант, придуманное/собственное название поля, что за поле это ясно из его названия...
Ольга (2006-08-22 06:46:00) [11]
> where T1.FirstKeyField is null
Это условие зачем? И что за зверь FirstKeyField?
Fay (2006-08-21 19:06:00) [12]delete T1
from T1 left join T2 on T1.ID1 = T2.ID1 and T1.ID2 = T2.ID2
where T1.FirstKeyField is null
Anatoly Podgoretsky (2006-08-21 19:05:00) [13]Это два разных по результату запроса
SELECT * FROM T1 a
WHERE NOT EXISTS(select id1, id2 from T2 b where a.id1=b.id1 and a.id2=b.id2)
Выбирается, то, что надо. Беру подзапрос в скобки, добавляю в начало:
DELETE FROM T1 WHERE EXISTS(подзапрос)
Ольга (2006-08-21 19:03:00) [14][5]
О, так значительно лучше. Где-то в подсознании (до сознания без помощи, к сожалению, не дошло) я именно это и хотела получить.
Спасибо!
Dok (2006-08-21 18:44:00) [15]delete FROM T1
WHERE NOT EXISTS (select * from T2 b where T1.id1=b.id1 and T1.id2=b.id2)
Dok (2006-08-21 18:43:00) [16]
> DELETE FROM T1 WHERE id1 IN (SELECT Id1 from T2 ...)
не очень гуд на больших выборках. всегда почти можно заменить на exists
Ольга (2006-08-21 18:17:00) [17]
> [2]
Где глупость поняла, спасибо.
> [1]
Да, так работает. Только конструкция получается громоздкая:
DELETE FROM T1
WHERE id1 IN
(
SELECT DISTINCT id1
FROM T1 a
WHERE NOT EXISTS (select id1 from T2 b where a.id1=b.id1 and a.id2=b.id2)
)
AND id2 IN
(SELECT DISTINCT id2
FROM T1 a
WHERE NOT EXISTS (select id2 from T2 b where a.id1=b.id1 and a.id2=b.id2)
)
Запрос строится динамически на произвольной таблице - удаление данных, не соответсвующих условиям внешнего ключа.
Можно как-то упростить этот запрос (а то программа становится не читабельной)?
clickmaker (2006-08-21 17:49:00) [18]DELETE FROM T1 WHERE id1 IN (SELECT Id1 from T2 ...)
Ega23 (2006-08-21 17:49:00) [19]
> DELETE FROM T1 WHERE EXISTS (подзапрос)
Exists - что возвращает? :о)