Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Удаление данных из таблицы с подзапросом [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 - что возвращает?  :о)


Наверх

Титульная страница Поиск, карта сайта Написать письмо