交叉连接行为(SQLServer 2008)

时间:2011-01-24 17:26:14

标签: sql sql-server sql-server-2008 outer-join cross-join

我一直试图通过我的查询来追踪问题。查询实际上是由HQL从HQL生成的,但生成的SQL没有达到我的预期。修改SQL会略微产生正确的结果,但我不确定为什么修改应该有所不同。

原始查询(不返回任何行)

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上。

2 个答案:

答案 0 :(得分:9)

JOIN的优先级高于COMMA,所以你的第二个语句被解释为(注意我添加的parens):

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

答案 1 :(得分:0)

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

在第一个中,或多或少明确地告诉他们“拿第一张桌子,与第二张桌子交叉加入,然后右边加入第三张,然后右边加入第四张”

在第二个中,交叉连接(至少以我的思维方式)隐式。这是从WHERE子句中执行所有连接的日子开始的“旧”SQL语法,再次,按照我的思维方式 - 意味着数据库引擎可以自由地按照自己的顺序进行操作。流程表。或者,换句话说,SQL没有给出连接表的特定顺序。 (使用内部连接和交叉连接,它没有区别,但是使用外部连接,它可以产生巨大的差异。)

...我更喜欢@ Joe的回答(upvoted),因为它在技术上是准确的。无论如何,我只是为了细节而把它扔给我自己。