Не удалось связать идентификатор из нескольких частей - PullRequest
174 голосов
/ 06 сентября 2011

Я видел похожие ошибки на 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: если я разделю запрос на 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;

Ответы [ 14 ]

203 голосов
/ 06 сентября 2011

Вы смешиваете неявные объединения с явными объединениями. Это разрешено, но вы должны знать, как это сделать правильно.

Дело в том, что явные объединения (те, которые реализованы с использованием ключевого слова JOIN) имеют приоритет над неявными (соединения "запятые", где условие соединения указано в предложении WHERE).

Вот схема вашего запроса:

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

Вы, вероятно, ожидаете, что он будет вести себя так:

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

, то есть комбинация таблиц a и b объединяется с таблицей 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

Здесь сначала объединяются таблицы a и b, затем результат соединяется с dkcd. По сути, это тот же запрос, что и у вас, только с использованием другого синтаксиса для одного из соединений, что имеет большое значение: ссылка a.maxa в условии соединения dkcd теперь абсолютно действительна.

Как правильно заметил @Aaron Bertrand, вы, вероятно, должны квалифицировать maxa с определенным псевдонимом, вероятно a, в предложении ORDER BY.

37 голосов
/ 20 октября 2014

Иногда эта ошибка возникает при неправильном использовании схемы (dbo) в запросе.

например, если вы напишите:

select dbo.prd.name
from dbo.product prd

вы получите ошибку.

В этих ситуациях измените его на:

select prd.name
from dbo.product prd
9 голосов
/ 05 декабря 2016

, если вы дали имя алиэса, измените его на фактическое имя

, например

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;

измените его на

SELECT  
    A.name,A.date
  FROM [LoginInfo].[dbo].[TableA] as A
   join 
  [LoginInfo].[dbo].[TableA] as B 
  on  A.name=B.name;
7 голосов
/ 18 мая 2017

Я боролся с тем же сообщением об ошибке в SQL SERVER, поскольку у меня было несколько объединений, изменение порядка соединений решило его для меня.

3 голосов
/ 02 апреля 2018

В моем случае проблема оказалась в псевдониме, который я дал таблице.«oa» кажется неприемлемым для SQL Server.

2 голосов
/ 19 ноября 2018

Для меня сработало изменение предложения WHERE в подзапрос SELECT

FROM:

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

TO:

    DELETE FROM CommentTag WHERE [dbo].CommentTag.NoteId = (SELECT NoteId FROM FetchedTagTransferData)
2 голосов
/ 28 февраля 2018

У меня была такая же ошибка от JDBC. Все проверил и мой запрос был в порядке. Оказалось, в предложении где у меня есть аргумент:

where s.some_column = ?

И значение аргумента, который я передавал, был нулевым. Это также дает ту же ошибку, которая вводит в заблуждение, потому что при поиске в Интернете вы обнаружите, что что-то не так со структурой запроса, но это не в моем случае Просто подумал, что кто-то может столкнуться с той же проблемой

1 голос
/ 15 августа 2018

Я также боролся с этой ошибкой и в итоге использовал ту же стратегию, что и ответ.Я включил свой ответ только для того, чтобы подтвердить, что это стратегия, которая должна работать.

Вот пример, где я делаю сначала одно внутреннее объединение двух таблиц, которые, как я знаю, получили данные, а затем два левых внешних объединения таблиц, которые могут иметь соответствующие строки, которые могут быть пустыми.Вы смешиваете внутренние и внешние объединения, чтобы получить результаты с данными по таблицам, вместо того, чтобы использовать синтаксис по умолчанию, разделенный запятыми, между таблицами и пропустить строки в желаемом соединении.

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]%')

Первое: выполните внутренние объединения между таблицами, для которых вы ожидаете совпадения данных.Вторая часть: Продолжите с внешними объединениями, чтобы попытаться получить данные в других таблицах, но это не отфильтрует ваш результирующий набор, если внешнее объединение таблицы не получило соответствующие данные или не соответствует условию, которое вы установили в предикате / условии on.

1 голос
/ 22 января 2018

Вы забыли присоединиться к некоторым столам?Если нет, то вам, вероятно, нужно использовать псевдонимы.

1 голос
/ 14 августа 2017

Моя ошибка заключалась в использовании поля, которого не было в таблице.

table1.field1 => не существует

table2.field1 => является правильным

Исправьте свое имя таблицы.

моя ошибка произошла из-за использования WITH

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

при использовании в соединении с другими таблицами ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...