具有多个连接的意外查询结果 - mysql

时间:2010-11-02 20:39:18

标签: sql mysql join

我有一个多表设置来处理在线购买交易。我从中获取数据的主表是购买活动表。它包含将其连接到地址表的ShipAcctID和将其连接到用户表的AcctID。 AcctID字段是对用户帐户ID的引用,该ID存储在users表中,但我需要返回的是他们的送货地址,该地址通过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

所以我需要通过purchase.AcctID = addresses.customer_id关系加入购买地址来获得billaddress;然后通过purchase.ShipAddrID = addresses.id关系将购买直接加入地址来获取shipaddress。无论如何,这在我的脑海里是有道理的。但是当我运行查询时,每个购买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

EDITS

斯蒂芬查询的结果:

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

名称与我在预期结果示例中显示的名称不同的原因是您的查询是从users表中提取名称,这不准确 - 用户名不一定与与给定用户关联的帐单或送货名称。这就是为什么我需要从地址表中提取这些值,而不是用户表。

4 个答案:

答案 0 :(得分:1)

虽然没有这样的重复项,但您可以为单个客户ID设置多个地址 - 这是示例中出现的情况,因为单次购买(1535)正在返回多个帐单地址(均为123 Park) Avenue和500 North Michigan Avenue)。

通常,客户可以拥有多个帐单邮寄地址(随着时间的推移),尽管每笔交易通常只有一个帐单邮寄地址。因此,我建议将一个BillAddrID字段添加到arrc_PurchaseActivity(如果它还没有),并将链接更改为jos_customers_addresses别名a1为p.BillAddrID = a2.id

或者,您可能希望(或已经)每个客户只有一个帐单邮寄地址,在这种情况下,您应该在您的客户表(用户,问题中)中添加帐单邮寄地址ID字段,然后将查询更改为链接从购买表到客户表,然后从客户的账单地址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

答案 1 :(得分:1)

要创建您想要的输出,您只需要两个表:
购买
地址表格

但是,您需要两次加入地址表:
一次用于结算地址
适用于送货地址

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

第一次INNER JOIN 链接到结算信息
第二次INNER JOIN 链接指向送货信息

答案 2 :(得分:0)

我确实在专家交流中得到了答案。我需要做的就是使用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

答案 3 :(得分:-2)

我认为没有理由根据您的标准两次加入同一张桌子......

尝试:

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。

编辑:

我怀疑它正在发生,因为你在不同的标准下对同一个表做了两个左外连接。