7

I have been trying to track down a problem with a query I have. The query is actually generated by hibernate from HQL but the resulting SQL doesn't do what I expect. Modifying the SQL slightly produces the correct result but I'm not sure why the modification should make any difference.

Original query (returns no rows)

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

Modified query - cross join replaced by a comma (implicit cross join)

Returns one row

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

My understanding, which may be incorrect is that writing from Table1 a, Table2 b is the same as writing from Table 1 a cross join Table2 b. So I don't understand why the queries return different results.

Is is something to do with the interaction between the cross join and the outer joins in the first query that causes this? I've looked at the query plans and second query plan looks reasonable. The first one has no outer joins at all which is strange.

This is on SQLServer 2008.

4

2 回答 2

9

JOIN 的优先级高于 COMMA,因此您的第二个语句被解释为(注意我添加的括号):

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

另请参阅:每个 SQL-99 的 JOIN 优先规则

于 2011-01-24T17:37:31.593 回答
0

在不查看实际数据和查询计划的情况下,我会说(好吧,猜测)它与优化器构建查询计划的方式有关。

在第一个中,或多或少明确地告诉“取第一个表,与第二个交叉连接,然后在第三个中右连接,然后在第四个中右连接”

其次,交叉连接是隐含的(至少在我看来是这样)。这是在 WHERE 子句中执行所有连接的日子以来的“旧” SQL 语法,这 - 再次,以我的思维方式 - 意味着数据库引擎可以自由地自行计算进程表。或者,换句话说,SQL 没有给出连接表的特定顺序。(对于内部连接和交叉连接,它没有区别,但对于外部连接,它可以产生巨大的差异。)

...我更喜欢@Joe 的回答(赞成),因为它在技术上是准确的。为了细节起见,我还是自己扔了它。

于 2011-01-24T17:41:48.523 回答