Неожиданные результаты запроса с несколькими объединениями - mysql - PullRequest
2 голосов
/ 02 ноября 2010

У меня есть настройка нескольких таблиц для обработки транзакций покупки онлайн. Основная таблица, из которой я получаю данные - это таблица покупательской активности. Он содержит ShipAcctID, который связывает его с таблицей адресов, и AcctID, который связывает его с таблицей пользователей. Поле AcctID является ссылкой на идентификатор учетной записи пользователя, который хранится в таблице пользователей, но мне нужно вернуть адрес доставки, который подключен в таблице адресов через поле customer_id.

Чтобы попытаться выяснить это, вот как на самом деле выглядят таблицы.

Таблица покупок

ID   |   PurchAmt   |   AcctID    | ShipAddrID
================================================
1    |   30.99      |   25        |  420
2    |   45.22      |   31        |  209

Таблица пользователей

ID   |   Name       
=================================
25   |   Anastasia Beaverhausen   
31   |   Charles Beaverhausen
45   |   Bennie Beaverhausen

Таблица адресов

ID   |   customer_id   | name                     |  address          
==========================================================================
300  |   25            | Anastasia Beaverhausen   | 123 Park Avenue  
209  |   31            | Charles Beaverhausen     | 500 5th Avenue   
420  |   45            | Bennie Beaverhausen      | 500 North Michigan Avenue

Что мне нужно сделать, это вернуть что-то вроде этого:

PurchaseID   |  PurchAmt  | billname                   |billAddress        |shipName           | shipaddress
====================================================================================================================================
1            |  30.99     | Anastasia Beaverhausen     |123 Park Avenue    |Bennie Beaverhausen  |500 North Michigan Avenue

Таким образом, мне нужно получить адрес электронной почты, соединив покупки по адресам с помощью отношения buyases.AcctID = address.customer_id; затем получите адрес отправителя, соединив покупки непосредственно с адресами через отношения buyases.ShipAddrID = address.id. В любом случае это имеет смысл в моей голове. Но когда я запускаю запрос, я получаю несколько строк для каждого идентификатора покупки, например:

PurchActvtyID | billName           | billAddress1             |shipName         |   shipAddress1
==================================================================================================================================
1535    |       Anastasia Beaverhausen | 123 Park Avenue          |Bennie Beaverhausen  | 500 North Michigan Avenue
1535    |       Bennie Beaverhausen    | 500 North Michigan Avenue  | Bennie Beaverhausen   | 500 North Michigan Avenue

Может кто-нибудь объяснить, почему это происходит? Я уверен, что это, вероятно, связано с тем, какой тип объединения использовать, но я не могу получить правильные результаты, независимо от того, какой тип я пробую. Вот мой запрос:

SELECT p.PurchActvtyID, a1.name AS billName, a1.address1 AS billAddress1, a2.name AS shipName, a2.address1 AS shipAddress1
FROM arrc_PurchaseActivity p
LEFT OUTER JOIN jos_customers_addresses a1 ON p.AcctID = a1.customer_id
LEFT OUTER JOIN jos_customers_addresses a2 ON p.ShipAddrID = a2.id

ORDER BY p.PurchActvtyID ASC

редактирует

Результаты запроса Стивена:

PurchActvtyID  |    billName   |    shipName   |    billAddress  |  shipAddress
========================================================================================

1535  | Esther Strom | Esther Strom |123 Park Avenue | 500 North Michigan Avenue

1535  | Esther Strom | Esther Strom |500 North Michigan Avenue |500 North Michigan Avenue

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

Ответы [ 4 ]

1 голос
/ 06 ноября 2010

Для создания нужного результата вам понадобятся только две таблицы:
Закупки Таблица
Адреса Таблица

Однако вам необходимо дважды присоединиться к таблице Адреса :
Один раз для Платежный адрес
Один раз для Адрес доставки

SELECT
t1.ID       as PurchaseID,
t1.PurchAmt as PurchAmt,
t2.name     as billname,
t2.address  as billaddress,
t3.name     as shipname,
t3.address  as shipaddress
FROM Purchases t1
INNER JOIN Addresses t2
        ON t1.AcctID
         = t2.customer_id
INNER JOIN Addresses t3
        ON t1.ShipAddrID
         = t3.ID

1st INNER JOIN ссылается на биллинг информацию
2nd INNER JOIN ссылается на доставку информацию

1 голос
/ 03 ноября 2010

Хотя дубликатов как таковых нет, у вас может быть несколько адресов для одного идентификатора клиента - это то, что происходит в примере, так как одна покупка (1535) возвращает несколько платежных адресов (оба 123 Park Авеню и 500 Северный Мичиган-авеню).

Обычно клиент может иметь много платежных адресов (с течением времени), хотя обычно на одну транзакцию приходится только один платежный адрес. Поэтому я предлагаю добавить поле BillAddrID в arrc_PurchaseActivity (если у него его еще нет) и изменить привязку к псевдониму jos_customers_addresses a1 на p.BillAddrID = a2.id.

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

РЕДАКТИРОВАТЬ, следующие комментарии:

Следующий запрос должен решить проблему с несколькими адресами, возвращаемыми в псевдониме выставления счета:

SELECT p.PurchActvtyID, a1.name AS billName, a1.address1 AS billAddress1, a2.name AS shipName, a2.address1 AS shipAddress1
FROM arrc_PurchaseActivity p
LEFT OUTER JOIN jos_customers_addresses a1 ON p.AcctID = a1.customer_id and a1.billing = 1
LEFT OUTER JOIN jos_customers_addresses a2 ON p.ShipAddrID = a2.id
ORDER BY p.PurchActvtyID ASC
0 голосов
/ 03 ноября 2010

Я получил ответ на этот вопрос на бирже экспертов.Все, что мне нужно было сделать, это использовать выражение group by.Итак, мой запрос теперь выглядит так:

SELECT p.PurchActvtyID, a1.name AS billName, a1.address1 AS billAddress1, a2.name AS shipName, a2.address1 AS shipAddress1
FROM arrc_PurchaseActivity p
LEFT OUTER JOIN jos_customers_addresses a1 ON p.AcctID = a1.customer_id
LEFT OUTER JOIN jos_customers_addresses a2 ON p.ShipAddrID = a2.id
GROUP BY p.PurchActvtyID
ORDER BY p.PurchActvtyID ASC
0 голосов
/ 02 ноября 2010

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

Попытка:

SELECT p.PurchActvtyID, a1.name AS billName, a1.address1 AS billAddress1, a1.name AS shipName, a1.address1 AS shipAddress1
FROM arrc_PurchaseActivity p
LEFT OUTER JOIN jos_customers_addresses a1 ON p.AcctID = a1.customer_id AND p.ShipAddrID = a1.id

ORDER BY p.PurchActvtyID ASC

Примечание - я работаю с SQL Server, я предполагаю, что синтаксис будет работать с MySQL.

Edit:

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

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