繁体   English   中英

对sql中两个表的列求和

[英]Sum columns from two tables in sql

我有两个表,一个是成本表,另一个是付款表,成本表包含产品的成本和产品名称。

 Cost Table
  id    |   cost   |  name
   1    |   100    |   A
   2    |   200    |   B
   3    |   200    |   A


  Payment Table
  pid  | amount    | costID
  1    |   10      |   1
  2    |   20      |   1
  3    |   30      |   2
  4    |   50      |   1

现在我必须按相同的name值对总费用求和,并按 costID 对总付款金额求和,如下面的查询

 totalTable

name | sum(cost)  |  sum(amount) |
  A  |  300       |     80       |
  B  |  200       |     30       |

但是,我一直在使用下面的查询来解决这个问题,但我认为我做错了。

                SELECT 
                    b.name,
                    b.sum(cost),
                    a.sum(amount)

                FROM 
                      `Payment Table` a

                 LEFT JOIN
                      `Cost Table` b 
                ON   
                      b.id=a.costID


                      GROUP by b.name,a.costID

如果有人能帮助我解决我的疑问或更好的想法,我将不胜感激。 谢谢

这应该有效:

select t2.name, sum(t2.cost), coalesce(sum(t1.amount), 0) as amount
from (
   select id, name, sum(cost) as cost
   from `Cost`
   group by id, name
) t2
left join (
   select costID, sum(amount) as amount
   from `Payment`
   group by CostID
) t1 on t2.id = t1.costID
group by t2.name

SQLFiddle

您需要在单独的查询中进行计算,然后将它们连接在一起。

  • 第一个是直截了当的。
  • 第二个,你需要得到name asociated基于在付款cost_id

SQL 小提琴演示

SELECT C.`name`, C.`sum_cost`, COALESCE(P.`sum_amount`,0 ) as `sum_amount`
FROM (
    SELECT `name`, SUM(`cost`) as `sum_cost`
    FROM `Cost`
    GROUP BY `name`
    ) C
LEFT JOIN (    
    SELECT `Cost`.`name`, SUM(`Payment`.`amount`) as `sum_amount`
    FROM `Payment`
    JOIN `Cost` 
       ON `Payment`.`costID` = `Cost`.`id`
    GROUP BY `Cost`.`name`
  ) P
  ON C.`name` =  P.`name`

输出

| name | sum_cost | sum_amount |
|------|----------|------------|
|    A |      300 |         80 |
|    B |      200 |         30 |

几个问题。 一方面,应该限定列引用,而不是聚合函数。

这是无效的:

 table_alias.SUM(column_name) 

应该:

 SUM(table_alias.column_name)

此查询应返回您要查找的前两列:

SELECT c.name         AS `name`
     , SUM(c.cost)    AS `sum(cost)`
  FROM `Cost Table` c
 GROUP BY c.name
 ORDER BY c.name

当您向另一个表(例如Product Table ,其中costid不是UNIQUE )引入连接时,您有可能生成(部分)笛卡尔积。

要查看它的样子,查看正在发生的事情,请删除GROUP BY和聚合SUM()函数,并查看带有连接操作的查询返回的详细信息行。

  SELECT c.id               AS `c.id`
       , c.cost             AS `c.cost`
       , c.name             AS `c.name`
       , p.pid              AS `p.pid`
       , p.amount           AS `p.amount`
       , p.costid           AS `p.costid`
    FROM `Cost Table` c
    LEFT
    JOIN `Payment Table` p
      ON p.costid = c.id
   ORDER BY c.id, p.pid

这将返回:

 c.id | c.cost |  c.name | p.pid | p.amount | p.costid
 1    |    100 |  A      | 1     |       10 | 1       
 1    |    100 |  A      | 2     |       20 | 1       
 1    |    100 |  A      | 4     |       50 | 1       
 2    |    200 |  B      | 3     |       30 | 2
 3    |    200 |  A      | NULL  |     NULL | NULL

请注意,我们从Cost Table中获得了 id=1 行的三个副本。

因此,如果我们修改该查询,添加GROUP BY c.name并将 c.cost 包装在 SUM() 聚合中,我们将获得总cost的膨胀值。

为避免这种情况,我们可以汇总Payment Tableamount ,因此每个costid只能获得一行。 然后,当我们执行连接操作时,我们不会从Cost生成行的重复副本。

下面就来汇总从总量查询Payment Table ,所以我们得到每一个单列costid

  SELECT p.costid
       , SUM(p.amount) AS tot_amount
    FROM `Payment Table` p 
   GROUP BY p.costid
   ORDER BY p.costid

那将返回:

  costid | tot_amount
  1      | 80
  2      | 30

通过使该查询成为“内联视图”,我们可以像使用表一样使用该查询的结果。 在这个例子中,我们为查询结果分配了一个别名v (在 MySQL 中,“内联视图”称为“派生表”。)

SELECT c.name                      AS `name`
     , SUM(c.cost)                 AS `sum_cost`
     , IFNULL(SUM(v.tot_amount),0) AS `sum_amount`
  FROM `Cost Table` c
  LEFT
  JOIN ( -- inline view to return total amount by costid 
         SELECT p.costid
              , SUM(p.amount) AS tot_amount
           FROM `Payment Table` p
          GROUP BY p.costid
          ORDER BY p.costid
       ) v
    ON v.costid = c.id
 GROUP BY c.name
 ORDER BY c.name

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM