Étrange requête de suppression, est-elle écrite correctement?

Nous avons récemment eu quelques problèmes où un script SQL qui supprimerait les inputs en double de la table n'utiliserait pas l'input la plus récente comme celle à conserver. Je pense que cette ligne est le problème

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) 

Est-ce la syntaxe correcte? J'ai trouvé une autre version du script travaillant sur une table différente. (les noms ont changé pour correspondre au premier exemple)

 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) 

Celui-ci utilise le nom de table de la table supprimée dans la clause inner where, cela peut-il causer un problème dans ma première version?

Détails sur la table:

  1. Toutes les colonnes qui se terminent par guid sont un type de données de uniqueidentifier
  2. vacc_pat_guid est la key primaire et est unique.
  3. date_given est une date-heure qui pourrait être nulle. S'il y a un doublon où l'un est nul et l'autre n'est pas nul, il devrait préférer celui qui n'est pas nul.

Sans aucun alias sur la première table, la requête est équivalente à:

 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) 

Et un bon serait

 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) 

En spécifiant le nom de la table dans la deuxième requête que vous nous montrez, l'optimiseur comprend qu'il doit se joindre à la première table, car la deuxième table s'appelle 'v', et la première est donc 'vacc_patient_details', et il ne confond pas .

Il est confus dans le premier parce qu'il ne sait pas si patient_guid est le champ dans le premier tableau ou dans le second. Donc, il prend le plus près, donc le second.

Modifier :

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

Si vous déclarez un alias pour une table, vous devez utiliser l'alias lorsque vous faites reference à la table:

DELETE t1 FROM test AS t1, test2 WHERE

Qu'il soit légal ou non de se joindre à la même table, ce n'est pas une bonne idée. Vous feriez mieux d'extraire les identifiants des loggings que vous pensez devoir supprimer dans un tableau séparé (vous pouvez alors vérifier qu'ils ont raison) et de les utiliser pour exécuter les suppressions.

Je pense qu'essayer de faire des suppressions en fonction d'une requête complexe comme celle-ci request des problèmes à un moment donné.

La section pertinente de votre code est (comme vous l'avez noté) ceci …

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

Le côté droit des opérateurs d'égalité n'a pas de table spécifiée. L'optimiseur vérifie d'abord la scope la plus locale pour une table correspondante. Dans ce cas, la table de la sous-requête a ces champs, l'optimisé ne vérifie même pas les tables de la requête externe.

La deuxième version du code est explicite sur la table à referencer, qui se trouve être la table dans la requête externe.

Donc, en bref, oui; Le problème est que la première version fait implicitement reference à l'instance de la requête de la requête interne et qu'elle doit à la place faire reference explicitement à l'instance de la requête de la requête externe.

Note: Je ne suis pas d'accord que cette auto-adhésion est un problème.

 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 

Essayez-le (dans votre environnement de développement, bien sûr)

 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)