考虑以下架构:
create table TableA (A1 int)
create table TableB (B1 int, B2 int)
create table TableC (C1 int, C2 int)
create table TableD (D1 int)
以下查询:
SELECT *
FROM TableA a
INNER JOIN TableB b ON b.B1=a.A1
INNER JOIN (SELECT TOP 1 *
FROM TableC c
WHERE c.C1=b.B1 ORDER BY c.C2) foo ON foo.C1=a.A1
INNER JOIN TableD d ON d.D1=foo.C1
在SQL Fiddle(SQL Server 2008)中,我得到以下结果:
The multi-part identifier "b.B1" could not be bound.: SELECT * FROM TableA a INNER JOIN TableB b ON b.B1=a.A1 INNER JOIN (SELECT TOP 1 * FROM TableC c WHERE c.C1=b.B1 ORDER BY c.C2) foo ON foo.C1=a.A1 INNER JOIN TableD d ON d.D1=foo.C1
但是用 CROSS APPLY 替换子查询的 INNER JOIN 修复了这个问题:
SELECT *
FROM TableA a
INNER JOIN TableB b ON b.B1=a.A1
CROSS APPLY (SELECT TOP 1 *
FROM TableC c
WHERE c.C1=b.B1 AND c.C1=a.A1 ORDER BY c.C2) foo
INNER JOIN TableD d ON d.D1=foo.C1
我的问题是:
1)为什么第一个查询失败?
2)为什么第二个查询没有失败?
3) CROSS APPLY 特定于SQL Server。哪个是这个问题的SQL标准解决方案?
重要提示:不要试图了解TableA,...,TableD背后的逻辑。它们只是一个更复杂的查询的抽象(很难阅读)。我想你会明白这个问题。
答案 0 :(得分:3)
from
子句中不允许使用相关子查询。这就是inner join
版本不起作用的原因。我实际上并不知道这个的历史。一个问题是你可以在依赖项中获得循环,虽然不难检测,但是无法处理查询。
cross apply
的查询是cross apply
非常适合的一种情况。但是,我不知道它在大数据上的执行情况如何。
这是尝试在标准SQL中重写它:
SELECT *
FROM TableA a
INNER JOIN TableB b ON b.B1=a.A1
INNER JOIN (select *
from (select c.*, row_number() over (partition by c1 order by c2)
FROM TableC c
) c
where seqnum = 1 and foo.C1=a.A1 and c.C1=b.B1
) foo
INNER JOIN TableD d ON d.D1=foo.C1