无法绑定多部分标识符

Pha*_*inh 186 sql sql-server sql-server-2005

我在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;
Run Code Online (Sandbox Code Playgroud)

当我执行此查询时,错误结果为: 无法绑定多部分标识符"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;
Run Code Online (Sandbox Code Playgroud)

SELECT  maxa ,
        COUNT(*) AS tong
FROM    khaosat
WHERE   CONVERT(DATETIME, ngaylap, 103) BETWEEN 'Sep 1 2011'
                                        AND     'Sep 5 2011'
GROUP BY maxa;
Run Code Online (Sandbox Code Playgroud)

And*_*y M 212

您正在将隐式连接与显式连接混合使用.这是允许的,但你需要知道如何正确地做到这一点.

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

以下是您的查询大纲:

SELECT
  …
FROM a, b LEFT JOIN dkcd ON …
WHERE …
Run Code Online (Sandbox Code Playgroud)

您可能希望它的行为如下:

SELECT
  …
FROM (a, b) LEFT JOIN dkcd ON …
WHERE …
Run Code Online (Sandbox Code Playgroud)

即,表的组合ab接合用表dkcd.事实上,正在发生的事情是

SELECT
  …
FROM a, (b LEFT JOIN dkcd ON …)
WHERE …
Run Code Online (Sandbox Code Playgroud)

也就是说,正如您可能已经理解的那样,只有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
Run Code Online (Sandbox Code Playgroud)

这里的表格a,并b首先连接,然后将结果接合dkcd.基本上,这是相同的查询是你的,只是使用不同的语法的连接,这使得有很大的差别之一:参考a.maxadkcd的连接条件是现在绝对有效.

正如@Aaron Bertrand正确指出的那样,你可能应该在条款中maxa使用特定的别名来限定.aORDER BY


Bob*_*obs 38

有时,当您以错误的方式在查询中使用架构(dbo)时会发生此错误.

例如,如果你写:

select dbo.prd.name
from dbo.product prd
Run Code Online (Sandbox Code Playgroud)

你会得到错误.

在这种情况下,将其更改为:

select prd.name
from dbo.product prd
Run Code Online (Sandbox Code Playgroud)

  • 这是一件非常烦人的事情,我花了很长时间才弄清楚。谢谢。最烦人的部分是有时它会对此喋喋不休,但有时它会正常进行 (2认同)

Ale*_*nov 11

如果你给了alies名称改变实际名称

例如

SELECT  
    A.name,A.date
  FROM [LoginInfo].[dbo].[TableA] as A
   join 
  [LoginInfo].[dbo].[TableA] as B 
  on  [LoginInfo].[dbo].[TableA].name=[LoginInfo].[dbo].[TableB].name;
Run Code Online (Sandbox Code Playgroud)

改变为

SELECT  
    A.name,A.date
  FROM [LoginInfo].[dbo].[TableA] as A
   join 
  [LoginInfo].[dbo].[TableA] as B 
  on  A.name=B.name;
Run Code Online (Sandbox Code Playgroud)

  • 另外,如果您正在构建 sql 字符串,请注意行尾是否缺少尾随空格。当它加入下面的下一个 INNER JOIN 行时,它将我的别名 M 转换为 MINNER 。显示执行的字符串的 SQL 探查器帮助解决了我的问题。(这里评论是因为它与别名v实际名称问题有关) (2认同)

小智 8

我在SQL SERVER中遇到同样的错误消息,因为我有多个连接,改变连接的顺序为我解决了它.


Has*_*tar 6

就我而言,问题出在我为表指定的别名上。SQL Server 似乎不接受“oa”。


Sau*_*out 5

对我有用的是将 WHERE 子句更改为 SELECT 子查询

从:

    DELETE FROM CommentTag WHERE [dbo].CommentTag.NoteId = [dbo].FetchedTagTransferData.IssueId
Run Code Online (Sandbox Code Playgroud)

到:

    DELETE FROM CommentTag WHERE [dbo].CommentTag.NoteId = (SELECT NoteId FROM FetchedTagTransferData)
Run Code Online (Sandbox Code Playgroud)