O identificador de várias partes não pôde ser vinculado

196

Vi erros semelhantes no SO, mas não encontro uma solução para o meu problema. Eu tenho uma consulta SQL como:

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;

Quando executo essa consulta, o resultado do erro é: O identificador de várias partes "a.maxa" não pôde ser vinculado. Por quê?
P / s: se eu dividir a consulta em 2 consultas individuais, execute ok.

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;

e

SELECT  maxa ,
        COUNT(*) AS tong
FROM    khaosat
WHERE   CONVERT(DATETIME, ngaylap, 103) BETWEEN 'Sep 1 2011'
                                        AND     'Sep 5 2011'
GROUP BY maxa;
PhamMinh
fonte
A phuongxatabela inclui uma coluna maxa?
Michael Petrotta
1
O que acontece se você adicionar um grupo por maxa, tong - logo após 5 de setembro de 2011.
user710502 6/11
Sim, tem. Se eu dividir a consulta para 2 subconsulta,-lo correr ok
PhamMinh
Parece que você está executando no banco de dados errado. Adicione uma instrução "USE [nome do banco de dados]" ao início da consulta e veja se você ainda recebe o erro.
Brian
1
Não, eu disse acima, se eu dividir a consulta em duas consultas individuais, ele funcionará okey.
PhamMinh

Respostas:

226

Você está misturando junções implícitas com junções explícitas. Isso é permitido, mas você precisa estar ciente de como fazer isso corretamente.

O fato é que as junções explícitas (aquelas implementadas usando a JOINpalavra - chave) têm precedência sobre as implícitas (as junções 'vírgula', em que a condição de junção é especificada na WHEREcláusula).

Aqui está um resumo da sua consulta:

SELECT
  
FROM a, b LEFT JOIN dkcd ON 
WHERE 

Você provavelmente espera que ele se comporte da seguinte maneira:

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

isto é, a combinação de tabelas ae bé associada à tabela dkcd. De fato, o que está acontecendo é

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

ou seja, como você já deve ter entendido, dkcdé unida especificamente contra be somente b, o resultado da junção é combinado ae filtrado ainda mais com a WHEREcláusula Nesse caso, qualquer referência a ana ONcláusula é inválida e adesconhecida nesse momento. É por isso que você está recebendo a mensagem de erro.

Se eu fosse você, provavelmente tentaria reescrever esta consulta e uma solução possível seria:

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

Aqui o mesas ae bsão unidas em primeiro lugar, em seguida, o resultado está ligado a dkcd. Basicamente, essa é a mesma consulta que a sua, usando apenas uma sintaxe diferente para uma das junções, o que faz uma grande diferença: a referência a.maxana dkcdcondição de junção da agora é absolutamente válida.

Como o @Aaron Bertrand observou corretamente, você provavelmente deve se qualificar maxacom um alias específico, provavelmente a, na ORDER BYcláusula.

Andriy M
fonte
ORDEM POR maxa ainda é ambíguo, não? Além disso, eu teria cuidado com '01 de setembro de 2011' como uma data, não funcionará com diferentes configurações de idioma / regionais.
Aaron Bertrand
@ Aaron: Concordo ORDER BY maxa, obrigado. Quanto às datas, acredito que foi assim que o OP optou por especificá-las em seu ambiente.
Andriy M
"junções explícitas ... têm precedência sobre implícitas" - você pode fornecer uma citação para isso, por favor? por exemplo, é definido nos padrões SQL ou é um recurso do produto? Obrigado.
precisa saber é o seguinte
1
@ onedaywhen: Receio que isso não seja mais que uma observação do meu lado até agora. Estou um pouco aliviado pelo fato de não ser o primeiro a falar sobre a precedência de junções aqui, mas, além disso, ficaria feliz em encontrar qualquer tipo de confirmação oficial.
Andriy M
1
No meu caso, eu estava esquecendo de colocar espaços quando concatenava as strings para construir o sql, então 'FROM dbo.table_a a' + 'INNER JOIN dbo.table_b b' se tornou 'FROM dbo.table_a aINNER JOIN dbo.table_b b', e ficou confuso e me deu essa mensagem de erro. Detalhes, detalhes, detalhes.
Guy Schalnat,
40

Às vezes, esse erro ocorre quando você usa seu esquema (dbo) na sua consulta de maneira errada.

por exemplo, se você escrever:

select dbo.prd.name
from dbo.product prd

você receberá o erro.

Nessas situações, altere-o para:

select prd.name
from dbo.product prd
Bobs
fonte
1
Este é bastante irritante e me levou muito tempo para descobrir isso. Thanx. A maioria parte chata é às vezes naggs sobre isso, mas outras vezes ele passa normaly
DanteTheSmith
12

se você deu o nome dos aliados, mude para o nome real

por exemplo

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;

mude isso para

SELECT  
    A.name,A.date
  FROM [LoginInfo].[dbo].[TableA] as A
   join 
  [LoginInfo].[dbo].[TableA] as B 
  on  A.name=B.name;
Alexander Zaldostanov
fonte
1
Além disso, se você estiver construindo a string sql, observe a falta de espaços à direita no final da linha. Ele converteu meu alias M em MINNER quando ingressou na próxima linha INNER JOIN abaixo. O criador de perfil SQL, mostrando a sequência executada, ajudou a resolver meu problema. (Comentado aqui como ela está relacionada com a questão apelido v nome real)
Simon
wow @Simon obrigado Eu nem pensei nisso e bati minha cabeça contra a parede tentando descobrir por que minha consulta não estava funcionando, estava faltando um espaço no final de um dos retornos de carro!
buradd 04/02
9

Eu estava lutando com a mesma mensagem de erro no SQL SERVER, uma vez que eu tinha várias associações, alterando a ordem das associações que a resolveu para mim.

Pavel M.
fonte
3

No meu caso, o problema acabou sendo o nome alternativo que eu havia dado à tabela. "oa" parece não ser aceitável para o SQL Server.

Hashim Akhtar
fonte
2

Eu estava tendo o mesmo erro do JDBC. Verifiquei tudo e minha consulta foi boa. Acabou que, na cláusula where, tenho uma discussão:

where s.some_column = ?

E o valor do argumento que eu estava passando era nulo. Isso também dá o mesmo erro que é enganoso, porque quando você pesquisa na Internet, acaba que algo está errado com a estrutura da consulta, mas não é o meu caso. Só pensei que alguém pode enfrentar o mesmo problema

xbmono
fonte
2

O que funcionou para mim foi transformar minha cláusula WHERE em uma subconsulta SELECT

DE:

    DELETE FROM CommentTag WHERE [dbo].CommentTag.NoteId = [dbo].FetchedTagTransferData.IssueId

PARA:

    DELETE FROM CommentTag WHERE [dbo].CommentTag.NoteId = (SELECT NoteId FROM FetchedTagTransferData)
SauerTrout
fonte
1

Sou novo no SQL, mas deparei-me com esse problema em um curso que eu estava fazendo e descobriu que atribuir a consulta ao projeto especificamente ajudou a eliminar o erro de várias partes. Por exemplo, o projeto que eu criei foi o CTU SQL Project, por isso tive certeza de iniciar meu script com USE [CTU SQL Project] como minha primeira linha, como abaixo.

USE [CTU SQL Project]
SELECT Advisors.First_Name, Advisors.Last_Name...and so on.
Bogartz
fonte
1
Quando você diz "projeto", presumo que você queira dizer banco de dados e não projeção. A declaração uso simplesmente muda qual banco de dados você está escopo da consulta para
Charleh
Sim, projeto Charleh como no banco de dados em que eu estava trabalhando. Não sabia ao certo o que estava fazendo de errado com meu banco de dados, mas a indicação "use" e o banco de dados específico ao escopo eliminaram meu erro.
Bogartz
1

Se esse erro ocorrer em um UPDATE, verifique JOINnovamente a tabela com a coluna / campo que está causando o erro.

No meu caso, isso ocorreu devido à falta do JOINpróprio, que gerou o mesmo erro devido a um campo desconhecido (como Andriy apontou ).

CPHPython
fonte
1

Em vez disso, você pode tentar ingressar em tabelas como,

select 
  .... 
from 
   dkcd 
     right join 
                a
                  , b

Isso deve funcionar

Suman Kumar
fonte
1
SELECT DISTINCT
        phuongxa.maxa ,
        quanhuyen.mahuyen ,
        phuongxa.tenxa ,
        quanhuyen.tenhuyen ,
        ISNULL(dkcd.tong, 0) AS tongdkcd
FROM    phuongxa ,
        quanhuyen
        LEFT OUTER JOIN ( SELECT    khaosat.maxa ,
                                    COUNT(*) AS tong
                          FROM      khaosat
                          WHERE     CONVERT(DATETIME, ngaylap, 103) BETWEEN 'Sep 1 2011'
                                                              AND
                                                              'Sep 5 2011'
                          GROUP BY  khaosat.maxa
                        ) AS dkcd ON dkcd.maxa = maxa
WHERE   phuongxa.maxa <> '99'
        AND LEFT(phuongxa.maxa, 2) = quanhuyen.mahuyen
ORDER BY maxa;
SVaidya
fonte
Use os próprios nomes da tabela em vez de usar o alias se surgir um problema de ligação de várias partes.
precisa saber é o seguinte
1

Meu erro foi usar um campo que não existia na tabela.

table1.field1 => não existe

table2.field1 => está correto

Corrija o seu nome da tabela.

meu erro ocorreu por causa do uso de WITH

WITH RCTE AS (
   SELECT...
)
SELECT RCTE.Name, ...
FROM 
  RCTE INNER JOIN Customer
  ON RCTE.CustomerID = Customer.ID 

quando usado em junção com outras tabelas ...

Zolfaghari
fonte
1

Você esqueceu de participar de algumas mesas? Caso contrário, você provavelmente precisará usar alguns aliases.

Tadej
fonte
1

Eu também estava lutando com esse erro e acabei com a mesma estratégia que a resposta. Estou incluindo minha resposta apenas para confirmar que esta é uma estratégia que deve funcionar.

Aqui está um exemplo em que eu faço primeiro uma junção interna entre duas tabelas que eu conheço obtém dados e, em seguida, duas junções externas deixadas em tabelas que podem ter linhas correspondentes que podem estar vazias. Você combina junções internas e externas para obter resultados com dados entre tabelas em vez de fazer a sintaxe separada por vírgula padrão entre tabelas e perder linhas na junção desejada.

use somedatabase
go 

select o.operationid, o.operatingdate, p.pasid, p.name as patientname, o.operationalunitid, f.name as operasjonsprogram,  o.theaterid as stueid, t.name as stuenavn, o.status as operasjonsstatus from operation o 
inner join patient p on o.operationid = p.operationid 
left outer join freshorganizationalunit f on f.freshorganizationalunitid = o.operationalunitid
left outer join theater t on t.theaterid = o.theaterid
where (p.Name like '%Male[0-9]%' or p.Name like '%KFemale [0-9]%')

Primeiro: faça as junções internas entre as tabelas que você espera que correspondam aos dados. Segunda parte: Continue com junções externas para tentar recuperar dados em outras tabelas, mas isso não filtrará seu conjunto de resultados se a junção externa da tabela não tiver dados correspondentes ou corresponder à condição configurada no predicado / condição on.

Tore Aurstad
fonte
0

Este erro também pode ser causado pela falta de uma vírgula ,entre os nomes das colunas na instrução SELECT.

por exemplo:

SELECT MyCol1, MyCol2 MyCol3 FROM SomeTable;
Andrew
fonte