我在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;

当我执行此查询时,错误结果是:
无法绑定(bind)多部分标识符“a.maxa”。 为什么?

P / s:如果我将查询分为2个单独的查询,则运行正常。
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子句进行进一步过滤。在这种情况下,对a子句中的ON的任何引用都是无效的,此时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。基本上,这是与您的查询相同的查询,只是对其中一个联接使用了不同的语法,这产生了很大的不同:a.maxa的联接条件中的引用dkcd现在绝对有效。

正如@Aaron Bertrand正确指出的那样,您应该在maxa子句中使用特定的别名(可能是a)来限定ORDER BY

08-28 16:06