2011-01-24 90 views
7

我一直在试图追查我遇到的查询问题。查询实际上是通过HQL从HQL生成的,但生成的SQL并没有达到我所期望的。稍微修改SQL会产生正确的结果,但我不确定为什么修改应该有所作为。交叉连接行为(SQLServer 2008)

原始查询(没有返回)

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 

修改后的查询 - 交叉连接逗号代替(隐式交叉连接)

返回一行

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 

我的理解,这可能不正确的是,写作from Table1 a, Table2 b与写作from Table 1 a cross join Table2 b相同。所以我不明白为什么查询返回不同的结果。

是否与第一个查询中导致此问题的交叉连接和外部连接之间的交互有关?我查看了查询计划,第二个查询计划看起来很合理。第一个没有外连接,这很奇怪。

这是SQLServer的2008年

回答

9

JOIN具有比逗号更高的优先级,让你的第二个发言被解释为(注意我加了括号):

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 

另请参见:JOIN precendence rules per SQL-99

+0

谢谢+1。在我的HQL中,我使用了COMMA,所以我不确定为什么Hibernate会渲染CROSS JOIN。我切换了from子句,所以Period表是最后一个,它正常工作。仍然产生了交叉连接,但是因为它的优先级是最后的,所以它按预期工作。 – 2011-01-24 18:01:03

0

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

在第一,它是或多或少明确告知“采取的第一个表,交叉与第二个连接,然后右连接中三分,然后在右四结合”

在第二,那交叉加入是(至少对我来说是这样)暗示。从WHERE子句中执行所有连接的时代开始,这就是“旧”的SQL语法,这也是我的思维方式 - 意味着数据库引擎可以自行解决执行进程表。换句话说,SQL并没有给出连接表的特定顺序。 (使用内部连接和交叉连接,没有区别,但使用外部连接可以产生巨大差异。)

...我更喜欢@ Joe的答案(upvoted),因为它在技术上是准确的。无论如何,我只是为了细节而抛弃它。