多部分的标识符无法被绑定

我在SO上看到过类似的错误,但我没有找到解决我问题的办法。 我有一个SQL查询,比如。

SELECT DISTINCT
        a.maxa ,
        b.mahuyen ,
        a.tenxa ,
        b.tenhuyen ,
        ISNULL(dkcd.tong, 0) AS tongdkcd
FROM    phuongxa a ,
        quanhuyen b
        LEFT OUTER JOIN ( SELECT    maxa ,
                                    COUNT(*) AS tong
                          FROM      khaosat
                          WHERE     CONVERT(DATETIME, ngaylap, 103) BETWEEN 'Sep 1 2011'
                                                              AND
                                                              'Sep 5 2011'
                          GROUP BY  maxa
                        ) AS dkcd ON dkcd.maxa = a.maxa
WHERE   a.maxa <> '99'
        AND LEFT(a.maxa, 2) = b.mahuyen
ORDER BY maxa;

当我执行这个查询时,错误的结果是。 多部分标识符"a.maxa"不能被绑定。为什么?
P/s: 如果我把这个查询分成两个单独的查询,它可以运行。

SELECT DISTINCT
        a.maxa ,
        b.mahuyen ,
        a.tenxa ,
        b.tenhuyen
FROM    phuongxa a ,
        quanhuyen b
WHERE   a.maxa <> '99'
        AND LEFT(a.maxa, 2) = b.mahuyen
ORDER BY maxa;

SELECT  maxa ,
        COUNT(*) AS tong
FROM    khaosat
WHERE   CONVERT(DATETIME, ngaylap, 103) BETWEEN 'Sep 1 2011'
                                        AND     'Sep 5 2011'
GROUP BY maxa;
解决办法

你把隐式连接和显式连接混在一起。这是被允许的,但你需要知道如何正确地做到这一点。

问题是,显式连接(使用JOIN关键字实现的连接)优先于隐式连接('逗号'连接,其中连接条件在WHERE子句中指定)。

下面是你的查询的概要。

SELECT
  …
FROM a, b LEFT JOIN dkcd ON …
WHERE …

你可能希望它表现得像这样。

SELECT
  …
FROM (a, b) LEFT JOIN dkcd ON …
WHERE …

也就是说,表ab的组合与表dkcd连接。事实上,所发生的情况是

SELECT
  …
FROM a, (b LEFT JOIN dkcd ON …)
WHERE …

也就是说,正如你可能已经理解的那样,dkcd是专门针对b连接的,而且只有b,然后连接的结果与a结合,并通过WHERE子句进一步过滤。在这种情况下,在ON子句中对a的任何引用都是无效的,a在此时是未知的。这就是为什么你会收到错误信息。

如果我是你,我可能会尝试重写这个查询,一个可能的解决方案是。

SELECT DISTINCT
  a.maxa,
  b.mahuyen,
  a.tenxa,
  b.tenhuyen,
  ISNULL(dkcd.tong, 0) AS tongdkcd
FROM phuongxa a
  INNER JOIN quanhuyen b ON LEFT(a.maxa, 2) = b.mahuyen
  LEFT OUTER JOIN (
    SELECT
      maxa,
      COUNT(*) AS tong
    FROM khaosat
    WHERE CONVERT(datetime, ngaylap, 103) BETWEEN 'Sep 1 2011' AND 'Sep 5 2011'
    GROUP BY maxa
  ) AS dkcd ON dkcd.maxa = a.maxa
WHERE a.maxa  '99'
ORDER BY a.maxa

这里首先连接表ab,然后将结果连接到dkcd。基本上,这和你的查询是一样的,只是对其中一个连接使用了不同的语法,这有很大的区别:dkcd'的连接条件中的引用a.maxa现在绝对有效。

正如@Aaron Bertrand所正确指出的,你可能应该在ORDER BY子句中用一个特定的别名来限定maxa,可能是a

评论(9)

有时,当你在查询中以错误的方式使用你的模式(dbo)时,会发生这个错误。

例如,如果你写道。

select dbo.prd.name
from dbo.product prd

你会得到一个错误。

在这种情况下,请将其改为。

select prd.name
from dbo.product prd
评论(1)

我是SQL的新手,但在我参加的一个课程中遇到了这个问题,并发现将查询指定给项目特别有助于消除多部分的错误。 例如,我创建的项目是CTU SQL项目,所以我确保我的脚本以USE [CTU SQL项目]作为第一行开始,如下所示。

USE [CTU SQL Project]
SELECT Advisors.First_Name, Advisors.Last_Name...and so on.
评论(2)