Mysql
 sql >> Base de données >  >> RDS >> Mysql

Comment ce SQL peut-il être faux ? Qu'est-ce que je ne vois pas ?

Ne mélangez pas la syntaxe de jointure de type virgule SQL-89 avec SQL-92 JOIN syntaxe. Il existe des problèmes subtils avec la priorité de ces deux types d'opérations de jointure.

Dans votre cas, la conséquence est qu'il évalue la condition de jointure LEFT JOIN avant le u l'alias de table existe. C'est pourquoi il ne sait pas ce que u.usr_auto_key est.

Vous pouvez corriger ce problème en utilisant JOIN syntaxe pour toutes les jointures :

SELECT 
  `u`.`usr_auto_key` AS `u__usr_auto_key`, 
  `s`.`set_auto_key` AS `s__set_auto_key`, 
  `u2`.`usr_auto_key` AS `u2__usr_auto_key`, 
  `u2`.`set_auto_key` AS `u2__set_auto_key`, 
  `u2`.`value` AS `u2__value` 
FROM `User` `u` JOIN `Setting` `s`
LEFT JOIN `User_Setting` `u2` ON `u`.`usr_auto_key` = `u2`.`usr_auto_key` 
WHERE (`s`.`sct_auto_key` = 1 AND `u`.`usr_auto_key` = 1 AND admin_property is null)

Je n'ai vu aucune condition de jointure entre u et s dans votre requête, donc je suppose que vous voulez qu'il s'agisse d'un produit cartésien ?

Pour plus de détails sur l'interaction entre les deux formes de syntaxe pour la jointure, consultez la section Join Processing Changes in MySQL 5.0.12 sur la page http://dev.mysql.com/doc/ refman/5.0/en/join.html

Concernant votre commentaire :comme je l'ai dit, cela a à voir avec la priorité des opérateurs. Si vous avez une requête SQL avec FROM A, B JOIN C puis il évalue le B JOIN C avant qu'il ne prête attention à A -- qui inclut l'attribution d'alias de table. Donc, si votre condition de jointure pour B JOIN C utilise l'alias de table pour A vous obtenez une erreur car cet alias n'existe pas encore.

Si vous l'inversez et exécutez B, A JOIN C puis lorsqu'il évalue la condition de jointure pour A JOIN C l'alias pour A est disponible et cela fonctionne (dans ce cas au moins).

Mais c'est une solution fragile, car vous pourriez aussi avoir besoin d'une requête qui ne peut pas être corrigée simplement en réorganisant A et B . Il est préférable d'arrêter d'utiliser la syntaxe de jointure obsolète avec des virgules. Ensuite, toute expression de jointure a accès à tous vos alias de table et vous n'aurez jamais ce problème dans aucune requête.