Mysql
 sql >> Database >  >> RDS >> Mysql

Come può questo SQL essere sbagliato? Cosa non vedo?

Non combinare la sintassi di join "stile virgola" SQL-89 con SQL-92 JOIN sintassi. Esistono sottili problemi con la precedenza di questi due tipi di operazioni di unione.

Nel tuo caso, la conseguenza è che sta valutando la condizione di join LEFT JOIN prima del u esiste un alias di tabella. Ecco perché non sa cosa u.usr_auto_key è.

Puoi correggere questo problema usando JOIN sintassi per tutti i join:

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)

Non ho visto alcuna condizione di unione tra u e s nella tua domanda, quindi presumo che intendi che questo sia un prodotto cartesiano?

Per maggiori dettagli sull'interazione tra i due moduli di sintassi per l'unione, vedere la sezione Modifiche all'elaborazione del join in MySQL 5.0.12 nella pagina http://dev.mysql.com/doc/ refman/5.0/en/join.html

Riguardo al tuo commento:come ho detto, ha a che fare con la precedenza dell'operatore. Se hai una query SQL con FROM A, B JOIN C quindi valuta il B JOIN C prima di prestare attenzione a A -- che include l'assegnazione di alias di tabella. Quindi, se la tua condizione di adesione per B JOIN C usa l'alias della tabella per A ricevi un errore perché quell'alias non esiste ancora.

Se lo annulli ed esegui B, A JOIN C quindi come valuta la condizione di unione per A JOIN C l'alias per A è disponibile e funziona (almeno in questo caso).

Ma questa è una soluzione fragile, perché potresti anche aver bisogno di una query che non può essere risolta semplicemente riordinando A e B . È meglio smettere di usare la sintassi di join obsoleta con le virgole. Quindi qualsiasi espressione di join ha accesso a tutti gli alias di tabella e non avrai mai questo problema in nessuna query.