Comportement de jointure croisée (SQLServer 2008)

J'ai essayé de traquer un problème avec une requête que j'ai. La requête est en fait générée par hibernate à partir de HQL mais le SQL qui en résulte ne fait pas ce que j'attends. Modifier le SQL produit légèrement le résultat correct, mais je ne suis pas sûr de savoir pourquoi la modification devrait faire une différence.

Requête originale (ne renvoie aucune ligne)

select sched.id, max(txn.dttm), acc.id from PaymentSchedulePeriod sched cross join PaymentSchedulePayment pay right outer join AccountTransaction txn on pay.accountTransactionFk=txn.id right outer join Account acc on txn.accountFk=acc.id where sched.accountFk=acc.id group by sched.id, acc.id 

Requête modifiée – jointure croisée remplacée par une virgule (jointure croisée implicite)

Renvoie une ligne

 select sched.id, max(txn.dttm), acc.id from PaymentSchedulePeriod sched ,PaymentSchedulePayment pay right outer join AccountTransaction txn on pay.accountTransactionFk=txn.id right outer join Account acc on txn.accountFk=acc.id where sched.accountFk=acc.id group by sched.id, acc.id 

Ma compréhension, qui peut être incorrecte, est que l'écriture à from Table1 a, Table2 b from Table 1 a cross join Table2 b from Table1 a, Table2 b est la même que l'écriture à from Table 1 a cross join Table2 b . Donc, je ne comprends pas pourquoi les requêtes returnnent des résultats différents.

Est-ce que cela a quelque chose à voir avec l'interaction entre la jointure croisée et les jointures externes dans la première requête qui provoque cela? J'ai regardé les plans de requête et le deuxième plan de requête semble raisonnable. Le premier n'a pas du tout de jointures extérieures, ce qui est étrange.

C'est sur SQL Server 2008.

JOIN a une priorité plus élevée qu'un COMMA, donc votre seconde instruction est interprétée comme (notez les parenthèses que j'ai ajoutées):

 select sched.id, max(txn.dttm), acc.id from PaymentSchedulePeriod sched ,(PaymentSchedulePayment pay right outer join AccountTransaction txn on pay.accountTransactionFk=txn.id right outer join Account acc on txn.accountFk=acc.id) where sched.accountFk=acc.id group by sched.id, acc.id 

Voir aussi: Règles de préconfiguration JOIN par SQL-99

Sans regarder datatables réelles et les plans de requête, je dirais (ok, devinez) cela a à voir avec la façon dont l'optimiseur construit les plans de requête.

Dans le premier cas, il est plus ou less explicitement dit de "prendre la première table, de la joindre avec la seconde, puis de la join à droite dans la troisième, puis de la join à droite dans la quasortingème"

Dans la seconde, cette jointure croisée est (au less à mon sens) implicite . C'est une "ancienne" syntaxe SQL à partir des jours où toutes les jointures ont été effectuées dans la clause WHERE, ce qui, selon moi, signifie que le moteur de database était libre de déterminer lui-même l'ordre dans lequel tables de process. Ou, en d'autres termes, SQL n'indique pas d'ordre spécifique dans lequel joindre des tables. (Avec des jointures internes et des jointures croisées, cela ne fait aucune différence, mais avec des jointures externes, cela peut faire une énorme différence.)

… Je préfère la réponse @ Joe (upvoted), car elle est techniquement exacte. Je le lance de toute façon pour des raisons de détail.