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:
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)