内部连接与交叉应用 - 无法绑定多部件标识符

时间:2013-02-02 00:18:50

标签: sql sql-server subquery inner-join cross-join

考虑以下架构:

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背后的逻辑。它们只是一个更复杂的查询的抽象(很难阅读)。我想你会明白这个问题。

1 个答案:

答案 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
相关问题