Странный запрос на удаление, правильно ли он написан? - PullRequest
0 голосов
/ 07 июля 2011

Недавно у нас были некоторые проблемы, когда SQL-скрипт, который удалял бы повторяющиеся записи из таблицы, не использовал бы самую последнюю запись в качестве сохраняемой.Я думаю, что эта строка является проблемой

delete from vaccine_patient_details 
where vacc_pat_guid <> 
    (Select top 1 vacc_pat_guid 
     from vaccine_patient_details as v 
     where v.patient_guid = patient_guid and 
           v.vaccine_guid = vaccine_guid 
     order by date_given desc)

Это правильный синтаксис?Я нашел другую версию скрипта, работающую на другом столе.(имена изменены, чтобы соответствовать первому примеру)

delete from vaccine_patient_details 
where vacc_pat_guid <> 
    (Select top 1 vacc_pat_guid 
     from vaccine_patient_details as v 
     where v.patient_guid = vaccine_patient_details.patient_guid and 
           v.vaccine_guid = vaccine_patient_details.vaccine_guid 
     order by date_given desc)

Этот использует имя таблицы удаленной таблицы во внутреннем предложении where, может ли это быть причиной проблемы в моей первой версии?

Подробная информация о таблице:

  1. Любые столбцы, заканчивающиеся на guid, представляют собой тип данных uniqueidentifier
  2. resp_pat_guid - это первичный ключ и является уникальным.дата и время, которые могут быть нулевыми.Если есть дубликат, в котором один равен нулю, а другой не равен нулю, он должен предпочесть ненулевой.

Ответы [ 5 ]

3 голосов
/ 07 июля 2011

Без каких-либо псевдонимов в первой таблице запрос эквивалентен:

delete from vaccine_patient_details 
where vacc_pat_guid <> 
    (Select top 1 vacc_pat_guid 
     from vaccine_patient_details as v 
     where v.patient_guid = v.patient_guid and 
           v.vaccine_guid = v.vaccine_guid 
     order by date_given desc)

И хорошим будет

delete v1 from vaccine_patient_details as v1
where v1.vacc_pat_guid <> 
    (Select top 1 v.vacc_pat_guid 
     from vaccine_patient_details as v 
     where v.patient_guid = v1.patient_guid and 
           v.vaccine_guid = v1.vaccine_guid 
     order by v.date_given desc)

Указав имя таблицы во втором запросевы показываете нам, оптимизатор понимает, что он должен соединиться с первой таблицей, потому что вторая таблица называется «v», а первая - «cinine_patient_details », и он не смущен.

Онзапутался в первом, потому что он не знает, является ли Patient_guid полем в первой таблице или во второй.Таким образом, он подходит ближе, поэтому второй.

Редактировать:

С http://dev.mysql.com/doc/refman/5.0/en/delete.html

Если вы объявляете псевдоним для таблицы, вы должны использоватьпсевдоним при обращении к таблице:

DELETE t1 FROM test AS t1, test2 WHERE ...

1 голос
/ 07 июля 2011
delete a from vaccine_patient_details a, vaccine_patient_details b
where a.patient_guid = b.patient_guid
   and a.vaccine_guid = b.vaccine_guid
   and a.date_given < b.date_given
1 голос
/ 07 июля 2011

Соответствующий раздел вашего кода (как вы заметили) это ...

 where v.patient_guid = patient_guid and 
       v.vaccine_guid = vaccine_guid

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

Вторая версия кода явно указывает на какую таблицу ссылаться, что происходитбыть таблицей во внешнем запросе.

Короче говоря, да;Проблема заключается в том, что первая версия неявно ссылается на экземпляр таблицы внутреннего запроса, и вместо этого она должна явно ссылаться на экземпляр таблицы внешнего запроса.

Примечание: я не согласен с тем, что это самостоятельное соединениепроблема.

0 голосов
/ 07 июля 2011

Попробуйте (конечно, в вашей среде разработки)

delete vaccine_patient_details 
  from vaccine_patient_details V
 where vacc_pat_guid <> 
    (Select top 1 vacc_pat_guid 
       from vaccine_patient_details 
      where V.patient_guid = patient_guid and 
            V.vaccine_guid = vaccine_guid 
      order by date_given desc)
0 голосов
/ 07 июля 2011

Законно или нет объединяться за одним столом, это не очень хорошая идея.Вы бы лучше извлекли идентификаторы записей, которые, по вашему мнению, должны быть удалены, в отдельную таблицу (тогда вы можете убедиться, что они правы), и используйте их для запуска удалений.удаление на основе сложного запроса, подобного этому, в какой-то момент вызывает проблемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...