#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.