Неможливо прив’язати ідентифікатор багаточастин


196

Я бачив подібні помилки на 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;

Чи phuongxaмістить таблиця стовпець maxa?
— Майкл Петротта

1
Що станеться, якщо ви додасте групу по maxa, tong - відразу після 5 вересня 2011 р.
— user710502

Так, є. Якщо я поділяю запит на 2 підзапроси, він працює нормально
— PhamMinh

Здається, що ви виконуєте неправильну базу даних. Додайте вираз "USE [ім'я бази даних]" до початку запиту і подивіться, чи все-таки ви отримаєте помилку.
— Брайан

1
Ні, я вже говорив вище, якщо я поділю запит на 2 індивідуальних запити, він запускається добре.
— PhamMinh

Відповіді:


226

Ви змішуєте неявні з'єднання з явними з'єднаннями. Це дозволено, але вам потрібно знати, як це зробити правильно.

Вся справа в тому, що явні приєднання (ті, які реалізовані за допомогою 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пункті.


ЗАМОВЛЕННЯ ПО maxa все ще неоднозначне, ні? Також я буду обережним з датою "1 вересня 2011 року", не працюватимуть з різними мовними / регіональними налаштуваннями.
— Аарон Бертран

@Aaron: Погодьтеся ORDER BY maxa, дякую. Що стосується дат, я вважаю, що саме так ОП обрала вказати їх у своєму середовищі.
— Андрій М

"явні приєднання ... мають перевагу над неявними", - чи можете ви надати цитування про це, будь ласка? наприклад, це визначено в стандартах SQL або це особливість продукту? Дякую.
— день, коли

1
@onedaywhen: Боюсь, це поки що не лише спостереження з мого боку. Мене дещо полегшує той факт, що я не в першу чергу говорю про перевагу приєднань, але, крім цього, я був би радий сам знайти будь-яке офіційне підтвердження.
— Андрій М

1
У моєму випадку я забував поставити пробіли, коли я об'єднав рядки для побудови sql, тому "ВІД dbo.table_a a" + "ВНУТРІШНЕ ПРИЄДНАННЯ dbo.table_b b 'стало" ВІД dbo.table_a aINNER JOIN dbo.table_b b', і він заплутався і дав мені це повідомлення про помилку. Деталі, деталі, деталі.
— Хлопець Шалнат

40

Іноді ця помилка виникає, коли ви неправильно використовуєте схему (dbo) у своєму запиті.

наприклад, якщо ви пишете:

select dbo.prd.name
from dbo.product prd

ви отримаєте помилку.

У цій ситуації змініть його на:

select prd.name
from dbo.product prd

1
Це досить дратує, і мені це було дуже довго, щоб зрозуміти це. Дякую. Найбільш дратівливу частину іноді це нудить про це, але в інший час це проходить нормально
— DanteTheSmith

12

якщо ви вказали ім'я псевдонімів, змініть його на фактичне ім'я

наприклад

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;

1
Крім того, якщо ви будуєте рядок sql, стежте за відсутністю пробілів у кінці рядка. Він перетворив мій псевдонім M у MINNER, коли він приєднався до наступного рядка INNER JOIN нижче. Профілер SQL, що показує виконаний рядок, допоміг вирішити мою проблему. (Прокоментується тут, як це пов’язано з псевдонімом щодо фактичного випуску імені)
— Саймон

wow @Simon спасибі, я навіть не думав про це і стукав головою об стіну, намагаючись зрозуміти, чому мій запит не працював, мені не вистачало місця в кінці однієї з рядків каретки повертається!
— buradd

9

Я боровся з тим самим повідомленням про помилку в SQL SERVER, оскільки у мене було декілька приєднань, змінивши порядок приєднань, вирішив це для мене.


3

У моєму випадку проблема виявилася псевдонімом, яке я дав таблиці. "oa" здається неприйнятним для SQL Server.


2

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

where s.some_column = ?

І значення аргументу, який я передавав, було нульовим. Це також дає ту саму помилку, яка вводить в оману, оскільки під час пошуку в Інтернеті ви виявите, що щось не так зі структурою запитів, але це не в моєму випадку. Просто подумав, що хтось може зіткнутися з тим же питанням


2

Що для мене спрацювало - змінити мій пункт WHERE на підбірку SELECT

ВІД:

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

ДО:

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

1

Я новачок у SQL, але натрапив на цю проблему під час курсу, який я брав, і виявив, що присвоєння запиту проекту спеціально допомогло усунути помилку в декількох частинах. Наприклад, проект, який я створив, - це проект CTU SQL, тому я переконався, що почав свій сценарій з USE [CTU SQL Project], як мій перший рядок, як показано нижче.

USE [CTU SQL Project]
SELECT Advisors.First_Name, Advisors.Last_Name...and so on.

1
Коли ви говорите "проект", я припускаю, що ви маєте на увазі базу даних, а не проекцію. Заява про використання просто змінює, до якої бази даних ви
— охоплюєте

Так, проект Charleh, як у базі даних, над якою я працював. Я не був впевнений, що я роблю неправильно зі своєю базою даних, але зазначив "використовувати" та конкретну базу даних для обсягу, усунув мою помилку.
— Богартц

1

Якщо ця помилка трапляється в UPDATE, двічі перевірте JOINтаблицю на таблиці зі стовпцем / полем, що викликає помилку.

У моєму випадку це було пов’язано з відсутністю самого JOINсебе, що генерувало ту саму помилку через невідоме поле (як вказував Андрій ).


1

Натомість ви можете спробувати приєднатись до таблиць, наприклад,

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

Це має спрацювати


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

1

Моя помилка полягала у використанні поля, якого не було в таблиці.

table1.field1 => не існує

table2.field1 => правильно

Виправте ім’я таблиці.

моя помилка сталася через використання слова

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

при використанні в поєднанні з іншими таблицями ...


1

Ви забули приєднатися до якихось таблиць? Якщо ні, то вам, ймовірно, потрібно використовувати псевдоніми.


1

Я також боровся з цією помилкою і закінчився тією ж стратегією, що і відповідь. Я включаю свою відповідь лише для того, щоб підтвердити, що це стратегія, яка повинна працювати.

Ось приклад, коли я роблю спочатку одне внутрішнє з'єднання між двома таблицями, за якими я знаю, отримані дані, а потім два лівих зовнішніх з'єднання на таблицях, які можуть мати відповідні рядки, які можуть бути порожніми. Ви змішуєте внутрішнє і зовнішнє з'єднання, щоб отримати результати з таблицями в таблицях, замість того, щоб робити синтаксис між таблицями, розділеним комами за замовчуванням, і пропускати рядки в бажаному об’єднанні.

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

По-перше: зробіть внутрішні з'єднання між таблицями, для яких очікується відповідність даних. Друга частина: Продовжуйте роботу з зовнішніми об'єднаннями, щоб спробувати отримати дані в інших таблицях, але це не відфільтрує ваш набір результатів, якщо зовнішнє з'єднання таблиці не отримало відповідних даних або збігається з умовою, яку ви встановили в предикаті / умові.


0

Ця помилка може бути викликана і просто пропуском коми , серед імен стовпців у операторі SELECT.

наприклад:

SELECT MyCol1, MyCol2 MyCol3 FROM SomeTable;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.