【问题标题】:multiple sums on grouped tables分组表上的多个总和
【发布时间】:2020-01-06 17:38:32
【问题描述】:
Table Header
+---------+-------+
| ref     | total | 
+---------+-------+
| 2544    |  2000 |
| 2544    |    10 |
| 2545    |  2566 |
| 2545    |    34 |
+---------+-------+

Table Items
+---------+-------+
| ref     | total | 
+---------+-------+
| 2544    |  1500 |
| 2544    |   500 |
| 2545    |  2000 |
| 2545    |   500 |
| 2545    |   100 |
+---------+-------+

我想对按 ref 分组的两个表中的总列求和,所以我的输出看起来像:

Output:
+---------+--------------+-------------+
| ref     | total_header | total_items | 
+---------+--------------+-------------+
| 2544    |        2010  |       2000  |
| 2545    |        2600  |       2600  |
+---------+--------------+-------------+

然后我可以比较两个总列并检查差异。

查询:

Select
    Header.ref,
    Sum(Header.total) as total_header
From
    Header
Group By
    Header.ref
Order By
    Header.ref Desc

这为我提供了 Header 表的正确信息。一旦我将 Items 表添加到查询中,total_header 和 total_items 就会给出错误的值

这是我正在使用的查询....

Select
    Header.ref,
    Sum(Header.total) as total_header,
    Sum(Items.total) as total_items
From
    Header Left Join
    Items On Header.ref = Items.ref
Group By
    Header.ref
Order By
    Header.ref Desc

谁能帮我创建一个可以产生上述输出的查询?此外,如果可能的话,使用另一列比较 2 个总列,根据它们是否匹配给出真或假。

谢谢,

马丁。

【问题讨论】:

  • 你应该在每张表上识别 PRIMARY KEY

标签: mysql sql group-by sum


【解决方案1】:

你可以先得到总和,然后加入他们 -

SELECT H.ref, H_TOT, I_TOT
FROM (SELECT ref, SUM(total) H_TOT
      FROM Header
      GROUP BY ref) H
JOIN (SELECT ref, SUM(total) I_TOT
      FROM Items
      GROUP BY ref) I ON H.ref = I.ref
ORDER BY H.ref

【讨论】:

  • 这完全取决于 OP 的意图。他可以使用 Inner 而不是 LEFT。
  • @forpas,已更新。
  • 好的,但正如我所说,这只有在每个表具有相同的不同参考时才有效。
【解决方案2】:

UNION ALL的2个表再聚合:

select t.ref,
  sum(t.total_header) total_header,
  sum(t.total_items) total_items,
  sum(t.total_header) = sum(t.total_items) matching
from (  
  select ref, total total_header, 0 total_items from Header
  union all
  select ref, 0 total_header, total total_items from Items
) t  
group by t.ref

请参阅demo
结果:

| ref  | total_header | total_items | matching |
| ---- | ------------ | ----------- | -------- |
| 2544 | 2010         | 2000        | 0        |
| 2545 | 2600         | 2600        | 1        |

【讨论】:

  • 谢谢,我使用了您的解决方案,因为 www.db-fiddle.com 在我扩展查询时被证明是一个方便的工具。谢谢
  • @MartinTrezise 你不接受我的回答有什么原因吗?
【解决方案3】:

可能的解决方案

SELECT refs.ref, sum_header.header_total, sum_items.items_total
FROM ( SELECT ref FROM header
       UNION
       SELECT ref FROM items ) refs
LEFT JOIN ( SELECT ref, SUM(total) header_total
            FROM header
            GROUP BY ref ) sum_header USING (ref)
LEFT JOIN ( SELECT ref, SUM(total) items_total
            FROM items
            GROUP BY ref ) sum_items USING (ref)

此解决方案的最佳情况是:

  1. SELECT COUNT(*)/COUNT(DISTINCT ref) 对于两个表来说都很高,~(10 或更多)。
  2. ref 在两个表中都有索引(另外在两个表的第一个子查询中尝试 SELECT DISTINCT ref FROM)。

【讨论】:

    【解决方案4】:

    你可以简单地使用

    Select ref, sum(header.total) as total_header, sum(items.total) as total_items
    from header,items where header.ref = items.ref
    group by ref
    order by ref desc
    

    【讨论】:

    • 你的查询和 OP 第二次查询有什么区别。
    • 我不明白什么是 OPs 查询
    • 你的查询会因为交叉连接相乘而给出错误的结果。 PS。 OP == 原始发帖人,问题作者。
    • @Akina,这不是交叉连接。他在 where 子句中使用了连接条件。
    • @AnkitBajpai “交叉连接相乘”是当一个连接的值因来自另一个连接的多个记录而相乘时产生的效果。它与CROSS JOIN 加入类型无关。我承认我把这个词曲解成英文了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多