«Не удалось связать многосоставный идентификатор ‘xxx'» при попытке объединить три таблицы

#mysql #sql #subquery #inner-join #distinct

#mysql #sql #Подзапрос #inner-join #distinct

Вопрос:

Я хотел бы начать с того факта, что я новичок в SQL с опытом работы всего 5 или 6 часов. Однако я быстро учусь.

В конечном итоге я пытаюсь выбрать адреса клиентов по линейке продуктов. Первая таблица (arinvch) содержит счета-фактуры и, следовательно, адреса клиентов; вторая таблица (aritrsh) содержит отдельные позиции счетов-фактур таблицы 1, а третья таблица (icitemh) содержит товарные позиции позиций.

Я попытался сначала объединить таблицы два и три в подзапросе, чтобы извлечь продуктовые линейки, а затем объединить их с первой таблицей, чтобы получить адреса клиентов по продуктовым линейкам.

Проще говоря, это то, что я пытался сделать:

 SELECT
   table1.addressinfo
FROM
   table1 
INNER JOIN
   (SELECT * FROM
   table2 INNER JOIN table3
   ON table2.itemnumber = table3.itemnumber
   WHERE table3.type = 'CRM') joinedtable
ON 
   table1.customernumber = joinedtable.customernumber; 
 

Точный код:

 SELECT
  arinvch.ccustno AS [Customer #],
  arinvch.dinvoice AS [Invoice Date],
  arinvch.cbcompany AS [Bill to Company],
  arinvch.cbaddr1 AS [Bill to Address 1],
  arinvch.cbaddr2 AS [Bill to Address 2],
  arinvch.cbcity AS [Bill to City],
  arinvch.cbstate AS [Bill to State],
  arinvch.cbzip AS [Bill to Zip Code],
  arinvch.cbcountry AS [Bill to Country],
  arinvch.cbphone AS [Bill to Phone],
  arinvch.cscompany AS [Ship To Company],
  arinvch.csaddr1 AS [Ship To Address 1],
  arinvch.csaddr2 AS [Ship To Address 2],
  arinvch.cscity AS [Ship To City],
  arinvch.csstate AS [Ship To State],
  arinvch.cszip AS [Ship To Zip Code],
  arinvch.cscountry AS [Ship To Country],
  arinvch.csphone AS [Ship To Phone],
  arinvch.cscontact AS [Ship To Contact],
  aritrsh.cinvno AS [Invoice #],
  aritrsh.citemno AS [Item Number],
  icitemh.citemno AS [Item #]
FROM
  arinvch 
  INNER JOIN
  (SELECT
  aritrsh.clineitem
  FROM 
  aritrsh 
  INNER JOIN 
  icitemh
  ON
  aritrsh.citemno = icitemh.citemno
  WHERE icitemh.ctype = 'CRM')table2
ON 
    arinvch.ccustno = aritrsh.ccustno;
 

Это возвращает следующее сообщение об ошибке (в FlySpeed SQL):

[FireDAC] [Phys] [ODBC] [Microsoft] [Драйвер сервера ODBC SQL] [SQL Server] Не удалось связать состоящий из нескольких частей идентификатор «aritrsh.ccustno».

Заранее спасибо! (Кроме того, в качестве дополнительной цели, если бы вы могли также объяснить, как я могу заставить адреса не повторяться, когда я извлекаю их из счетов, это было бы здорово. Я пытался включить SELECT DISTINCT во многих местах, но, похоже, не могу найти решение (поскольку я хочу, чтобы table1.customernumber был distinct, а DISTINCT не имеет значения).)

Ответ №1:

Вам не нужен подзапрос:

 FROM arinvch INNER JOIN
     aritrsh
     ON arinvch.ccustno = aritrsh.ccustno INNER JOIN
     icitemh
     ON aritrsh.citemno = icitemh.citemno AND icitemh.ctype = 'CRM'
 

Логику проще понять без подзапросов. Я бы использовал псевдонимы таблиц для запроса:

 FROM arinvch n INNER JOIN
     aritrsh t
     ON n.ccustno = t.ccustno INNER JOIN
     icitemh i
     ON t.citemno = i.citemno AND i.ctype = 'CRM'
 

Это упрощает запись и чтение запроса.

Комментарии:

1. Попробовал это. Не сработало. При выполнении кода не возникло никаких ошибок, однако и записей тоже не появилось. Есть идеи относительно того, почему?

2. Начните с одного объединения, а затем добавьте еще. По-видимому, данные в таблицах не совпадают.

Ответ №2:

     arinvch 
    JOIN ( 
        SELECT aritrsh.clineitem
        FROM aritrsh 
            JOIN icitemh ON
                aritrsh.citemno = icitemh.citemno
        WHERE icitemh.ctype = 'CRM'
        ) table2 ON 
        arinvch.ccustno = aritrsh.ccustno;
 

вторая таблица — table2 в вашем примере, а не aritrsh.

Для второй части: arinvch (1: M) -> aritrsh и aritrsh (1: 1) -> icitemh

у aritrsh будет 1 или более продуктов, заказанных клиентами. Это повторит поля адреса для каждого заказанного продукта. Вы могли бы обобщить все это, заключив весь оператор select в круглые скобки, а затем использовать group by для удаления записей счета.

 select a, b, c, d
from ( big select statement above ) A
group by a, b, c, d
 

группа by удалит дубликаты (точно так же, как distinct.) Замените a, b, c, d именами ваших полей во внутреннем select без префиксов, таких как aritrsh., но имейте только поля, которые имеют отношение к адресу и продуктам, а не к строкам счета.

Комментарии:

1. Я исправил свою ошибку и заменил aritrsh.ccustno на table2.ccustno. К сожалению, появилась следующая ошибка: [FireDAC] [Phys] [ODBC] [Microsoft] [Собственный клиент SQL Server 10.0] [SQL Server] Недопустимое имя столбца ‘ccustno’.

2. Я могу заверить вас, что ccustno действительно является именем столбца в нашем SQL server, присутствующим в arinvch и aritrsh.