Domanda

Ho cercato di rintracciare un problema con una query che ho. La query è in realtà generato da Hibernate dalla HQL ma la risultante di SQL non fa quello che mi aspetto. Modifica del SQL leggermente produce il risultato corretto, ma non sono sicuro perché la modifica dovrebbe fare alcuna differenza.

query originale (non restituisce alcuna riga)

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

query modificata - cross join sostituito da una virgola (croce implicite uniscono)

restituisce una riga

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

La mia comprensione, che può essere corretto è che la scrittura from Table1 a, Table2 b è lo stesso di scrittura from Table 1 a cross join Table2 b. Quindi non capisco il motivo per cui le query restituiscono risultati diversi.

Is è qualcosa a che fare con l'interazione tra i cross join e outer join nella prima query che causa questo? Ho guardato i piani di query e il secondo piano di query sembra ragionevole. Il primo non ha outer join a tutti che è strano.

Questo è lo SQLServer 2008.

È stato utile?

Soluzione

JOIN ha una precedenza maggiore di una virgola, così la vostra seconda istruzione viene interpretata come (nota le parentesi ho aggiunto):

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

Vedi anche: ISCRIVITI regole precendenza per SQL-99

Altri suggerimenti

Senza guardare i dati effettivi e dei piani di query, direi (ok, indovinare) ha a che fare con il modo in cui l'ottimizzatore costruisce i piani di query.

Nel primo, è più o meno esplicitamente detto di "prendere la prima tabella, croce si uniscono con il secondo, poi unirsi a destra nel terzo, poi unirsi a destra nel quarto"

Nella seconda, quella croce si uniscono è (almeno a mio modo di pensare) implicita . Questo è "vecchio" sintassi SQL dai tempi in cui tutti i join sono stati eseguiti in clausola WHERE, che - ancora una volta, al mio modo di pensare - significa che il motore di database era libero di lavorare per proprio conto l'ordine in cui le tabelle di processo. O, in altre parole, SQL non è in corso di dare un ordine specifico in cui unire le tabelle. (Con inner join e croce si unisce, non fa alcuna differenza, ma con outer join, può fare una grande differenza.)

... Io preferisco @ risposta di Joe (upvoted), in quanto è tecnicamente accurata. Sto lanciandolo mia comunque solo per amor di dettagli.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top