简体   繁体   English

对sql中两个表的列求和

[英]Sum columns from two tables in sql

I have two tables, one is the cost table and the other is the payment table, the cost table contains the cost of product with the product name.我有两个表,一个是成本表,另一个是付款表,成本表包含产品的成本和产品名称。

 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

Now I have to sum the total of cost by the same name values, and as well sum the total amount of payments by the costID, like the query below现在我必须按相同的name值对总费用求和,并按 costID 对总付款金额求和,如下面的查询

 totalTable

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

However I have been working my way around this using the query below but I think I am doing it very wrong.但是,我一直在使用下面的查询来解决这个问题,但我认为我做错了。

                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

I would be grateful if somebody would help me with my queries or better still an idea as to how to go about it.如果有人能帮助我解决我的疑问或更好的想法,我将不胜感激。 Thank you谢谢

This should work:这应该有效:

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 SQLFiddle

You need do the calculation in separated query and then join them together.您需要在单独的查询中进行计算,然后将它们连接在一起。

  • First one is straight forward.第一个是直截了当的。
  • Second one you need to get the name asociated to that payment based in the cost_id第二个,你需要得到name asociated基于在付款cost_id

SQL Fiddle Demo 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`

OUTPUT输出

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

A couple of issues.几个问题。 For one thing, the column references should be qualified, not the aggregate functions.一方面,应该限定列引用,而不是聚合函数。

This is invalid:这是无效的:

 table_alias.SUM(column_name) 

Should be:应该:

 SUM(table_alias.column_name)

This query should return the first two columns you are looking for:此查询应返回您要查找的前两列:

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

When you introduce a join to another table, like Product Table , where costid is not UNIQUE, you have the potential to produce a (partial) Cartesian product.当您向另一个表(例如Product Table ,其中costid不是UNIQUE )引入连接时,您有可能生成(部分)笛卡尔积。

To see what that looks like, to see what's happening, remove the GROUP BY and the aggregate SUM() functions, and take a look at the detail rows returned by a query with the join operation.要查看它的样子,查看正在发生的事情,请删除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

That's going to return:这将返回:

 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

Notice that we are getting three copies of the id=1 row from Cost Table .请注意,我们从Cost Table中获得了 id=1 行的三个副本。

So, if we modified that query, adding a GROUP BY c.name , and wrapping c.cost in a SUM() aggregate, we're going to get an inflated value for total cost .因此,如果我们修改该查询,添加GROUP BY c.name并将 c.cost 包装在 SUM() 聚合中,我们将获得总cost的膨胀值。

To avoid that, we can aggregate the amount from the Payment Table , so we get only one row for each costid .为避免这种情况,我们可以汇总Payment Tableamount ,因此每个costid只能获得一行。 Then when we do the join operation, we won't be producing duplicate copies of rows from Cost .然后,当我们执行连接操作时,我们不会从Cost生成行的重复副本。

Here's a query to aggregate the total amount from the Payment Table , so we get a single row for each costid .下面就来汇总从总量查询Payment Table ,所以我们得到每一个单列costid

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

That would return:那将返回:

  costid | tot_amount
  1      | 80
  2      | 30

We can use the results from that query as if it were a table, by making that query an "inline view".通过使该查询成为“内联视图”,我们可以像使用表一样使用该查询的结果。 In this example, we assign an alias of v to the query results.在这个例子中,我们为查询结果分配了一个别名v (In the MySQL venacular, an "inline view" is called a "derived table".) (在 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