我一直试图通过我的查询来追踪问题。查询实际上是由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上。
答案 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
答案 1 :(得分:0)
不看实际数据和查询计划,我会说(好吧,猜测)它与优化器构建查询计划的方式有关。
在第一个中,或多或少明确地告诉他们“拿第一张桌子,与第二张桌子交叉加入,然后右边加入第三张,然后右边加入第四张”
在第二个中,交叉连接(至少以我的思维方式)隐式。这是从WHERE子句中执行所有连接的日子开始的“旧”SQL语法,再次,按照我的思维方式 - 意味着数据库引擎可以自由地按照自己的顺序进行操作。流程表。或者,换句话说,SQL没有给出连接表的特定顺序。 (使用内部连接和交叉连接,它没有区别,但是使用外部连接,它可以产生巨大的差异。)
...我更喜欢@ Joe的回答(upvoted),因为它在技术上是准确的。无论如何,我只是为了细节而把它扔给我自己。