如何连接三个表以获得总和

Posted

技术标签:

【中文标题】如何连接三个表以获得总和【英文标题】:How to join three tables to get Sum 【发布时间】:2015-04-26 14:47:49 【问题描述】:

我有三个表:Products、Purchase、Invoice

产品表: Productct_no     名称 1                        A 2                        B 3                        C

采购表: Purchase_no    Product_no    数量 001                    1                    81 002                    2                    150 003                    3                    10

发票表: 发票编号    产品编号    数量 001                    1                 20 002                    2                 10 003                    3                 10

我想获取每个产品的采购数量和发票数量,我使用了以下查询

选择 PR.product_no, sum(P.qty),sum(I.qty) FROM 产品公关 LEFT JOIN invoice I ON I.product_no=PR.product_no LEFT JOIN 购买 P ON P.product_no=PR.product_no 按 PR.product_no 分组

product_no    sum(P.qty)    sum(I.qty) 001                    162             160 002                    150             50 003                    10               10

编辑:预期结果 product_no    sum(P.qty)    sum(I.qty) 001                    81             20 002                    150             10 003                    10               10

我的查询给了我错误的响应(数量总和错误),请帮助我更正我的查询以正确获得结果。谢谢

【问题讨论】:

您的预期结果是什么? 省略总和和分组依据,看看返回了什么结果,这样你就知道你在求和什么数据。 无论如何看起来像是一对一的映射。分组似乎是多余的 这里好像有几个错别字,不清楚你的意思。在您的结果表中,您有两次 sum(P.qty)。也很清楚你想要什么;每个产品在每个表上只存在一次,所以不清楚为什么要总和而不是结果? @pala_ 我认为这不是现实中的 1:1 映射。可能有其他发票和相同产品的购买,该示例仅显示 1:1 映射。我怀疑上面显示的数据不完整。此外,如果任一左连接返回多于一行(我怀疑它实际上是这样),则由于扇出,这是执行此查询的错误方法。 【参考方案1】:

根据所提供的信息,我认为您的示例数据并不真正是您所拥有的。我在这里最好的猜测是,您的查询正在对这些连接中的一个或两个进行扇出,这会弄乱您的总和。您需要分别对它们求和,否则这些连接中的任何一个中的附加行都会扇出另一个连接,从而在总和中复制您的结果。这在您的结果中很明显,因为 001 看起来是双倍的(即使您的示例数据没有显示它)。

这样可以确保总和彼此独立:

SELECT PR.product_no, 
    ( SELECT sum(I.qty)
      FROM invoice I 
      WHERE I.product_no=PR.product_no ) invoice_qty,
    ( SELECT sum(P.qty)
      FROM purchase P 
      WHERE P.product_no=PR.product_no ) purchase_qty
FROM products PR 

【讨论】:

非常感谢,您的回答对我有帮助。【参考方案2】:

我认为您的 GROUP BY 有问题。在这种情况下我会做这样的事情

SELECT P.Product_no, Inv.InvProdSum, Pur.PurProdSum
FROM Product P
LEFT JOIN (SELECT Product_no, SUM(Qty) AS InvProdSum
          FROM Invoice 
          GROUP BY Product_no) AS Inv
ON P.Product_no = Inv.Product_no
LEFT  JOIN (SELECT Product_no, SUM(Qty) AS PurProdSum
            FROM Purchase 
            GROUP BY Product_no) AS Pur
ON P.Product_no = Pur.Product_no

这是http://sqlfiddle.com/#!9/731a5/1的SQL Fiddle

注意我在这里添加了一些额外的值来测试它是如何工作的......

GL!

【讨论】:

这并没有给我预期的结果,我使用 Group by 因为我在 Invoice 和 Purchase 表中有很多 product_no 记录,我简化了这个问题的表。谢谢 @Azmath 我不明白,我得到的结果与您在测试时想要得到的结果完全相同...我知道您想对表 Invoice 和 Purchase 中具有相同 product_no 的所有值求和并将其显示在我的查询完全执行的一张表中...here...无论如何祝你好运,我希望你能找到你的解决方案:) 您的回答有效,这是我的错,我的问题很混乱,但您解决了非常感谢。 @Azmath 是的,我看到你找到了解决方案 woot 解决它:)。很高兴你做到了,这很重要。【参考方案3】:

这是我没有子查询的解决方案:

with 
  product(product_no, name) as (values
  (1, 'A'),
  (2, 'B'),
  (3, 'C')
),
  purchase(purchase_no, product_no, qty) as (values
  ('001', 1, 81),
  ('002', 2, 150),
  ('003', 3, 10),
  ('004', 1, 1000)
),
  invoice(invoice_no, product_no, qty) as (values
  ('001', 1, 20),
  ('002', 2, 10),
  ('003', 3, 10),
  ('004', 2, 5000)
),
  mixed as
(select d.product_no,
  purchase_no, p.qty as qty_purchase, 
  invoice_no, i.qty as qty_invoice,
  row_number() over(partition by purchase_no) as rn_purchase,
  row_number() over(partition by invoice_no) as rn_invoice
from product d
left join purchase p on p.product_no = d.product_no 
left join invoice i on i.product_no = d.product_no
)
select product_no,
  sum((case when rn_purchase = 1 then 1 else 0 end) * qty_purchase) as sum_purchase,
  sum((case when rn_invoice = 1 then 1 else 0 end) * qty_invoice) as sum_invoice
from mixed 
group by product_no
order by product_no
;

结果:

product_no|sum_purchase|sum_invoice|
----------|------------|-----------|
         1|        1081|         20|
         2|         150|       5010|
         3|          10|         10|

【讨论】:

以上是关于如何连接三个表以获得总和的主要内容,如果未能解决你的问题,请参考以下文章

连接表以获取总和 - SQL/Access

如何连接两个表以获得以下结果?

查找从三个表的左连接获得的三列的总和

使用两个不同的外键连接两个表以获得相同的字段

努力正确连接多个表以接收正确的数据

如何连接表以选择连接表中的最大行? [复制]