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


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.