【问题标题】:Group and Sum from multiple tables in MySQLMySQL中多个表的分组和求和
【发布时间】:2019-02-02 23:36:29
【问题描述】:

我想根据前两列对 2 个表进行分组。我已成功完成此操作,代码如下所示。 我需要一些帮助来对每个表中的剩余列进行求和,并使用重命名的列插入到我的输出表中,如下所示。 在输出中,FORECAST 列是 MI_STAT_TOTAL 表的结果,SALES 列是 SALES_TOTAL 表的结果。

表:MI_STAT_TOTAL

Planning_Hierarchy_2  Region_Description          Measure_Values
xx                    LATAM                        2   
yy                    ASPAC                        3
zz                    EMEA                         4
zz                    EMEA                         1
aa                    ASPAC                        1

表格:SALES_TOTAL

Product_Number        Region                      Item_Values
xx                    LATAM                        1  
yy                    ASPAC                        2
zz                    EMEA                         2
zz                    EMEA                         1
bb                    USA                          2

预期输出 表:P2_Region_Unique

Product_Number        Region                      Forecast       Sales
xx                    LATAM                        2             1
yy                    ASPAC                        3             2
zz                    EMEA                         5             3 
aa                    ASPAC                        1
bb                    USA                                        2

下面的代码只考虑两个表之间的 GROUP BY 而不是 SUM:

CREATE TABLE P2_Region_Unique (
  Product_Number VARCHAR(100),
  Region VARCHAR(13)
  );

INSERT INTO P2_Region_Unique
    SELECT s.Planning_Hierarchy_2 AS Product_Number, s.Region_Description` AS Region
    FROM MI_STAT_TOTAL s
    UNION
    SELECT m.`Product Number` AS `Product_Number`, m.`Region` AS Region
    FROM SALES_TOTAL m;

考虑到 SUM 也包括在内的预期输出表格式

CREATE TABLE P2_Region_Unique (
  `Product Number` VARCHAR(100),
  `Region` VARCHAR(13),
  `Forecast` DECIMAL (20,10),
  `Sales` DECIMAL (20,10)
  );

【问题讨论】:

  • 存储派生数据通常不是一个好主意

标签: mysql sql


【解决方案1】:

在 MySQL 中,您可以使用 INSERT ... SELECT syntaxSELECT 转换为 INSERT

您的样本数据表明您正在处理 N-M 连接。首先要做的是将聚合移动到子查询中,如下所示:

INSERT INTO P2_Region_Unique
SELECT s.product_number, s.region, f.forecast, s.sales
FROM
    (
        SELECT product_number, region, SUM(item_values) sales
        FROM SALES_TOTAL
        GROUP BY product_number, region
    ) s
    LEFT JOIN (
        SELECT planning_hierarchy_2 product_number, region_description region, SUM(measure_values) forecast
        FROM MI_STAT_TOTAL
        GROUP BY planning_hierarchy_2, region_description
    ) f ON f.product_number = s.product_number AND f.region = s.region
GROUP BY s.product_number, s.region

这将起作用,但不会从连接的两端返回记录。为此,您可以使用 UNIONed 查询来模拟 FULL OUTER JOIN(正如@Nick 指出的那样,MySQL 不支持),例如:

INSERT INTO P2_Region_Unique
SELECT s.product_number, s.region, f.forecast, s.sales
FROM
    (
        SELECT product_number, region, SUM(item_values) sales
        FROM SALES_TOTAL
        GROUP BY product_number, region
    ) s
    LEFT JOIN (
        SELECT planning_hierarchy_2 product_number, region_description region, SUM(measure_values) forecast
        FROM MI_STAT_TOTAL
        GROUP BY planning_hierarchy_2, region_description
    ) f ON f.product_number = s.product_number AND f.region = s.region
GROUP BY s.product_number, s.region
UNION
SELECT f.product_number, f.region, f.forecast, s.sales
FROM
    (
        SELECT planning_hierarchy_2 product_number, region_description region, SUM(measure_values) forecast
        FROM MI_STAT_TOTAL
        GROUP BY planning_hierarchy_2, region_description
    ) f
    LEFT JOIN (
        SELECT product_number, region, SUM(item_values) sales
        FROM SALES_TOTAL
        GROUP BY product_number, region
    ) s ON f.product_number = s.product_number AND f.region = s.region
GROUP BY f.product_number, f.region

UNION 运算符消除子查询之间的重复。

demo on DB Fiddle 产生:

| product_number | region | forecast | sales |
| -------------- | ------ | -------- | ----- |
| aa             | ASPAC  | 1        |       |
| bb             | USA    |          | 2     |
| xx             | LATAM  | 2        | 1     |
| yy             | ASPAC  | 3        | 2     |
| zz             | EMEA   | 5        | 3     |

【讨论】:

  • 截至 2019 年 2 月,no 版本的 MySQL 支持 FULL OUTER JOIN
  • @Nick :啊,好吧,我不知道,谢谢!好的,所以我回滚了对以前版本的回答,该版本没有使用FULL OUTER JOIN
  • @GMB 在您的代码中是否有任何方法可以在不使用 FULL OUTER JOIN 语句的情况下进行完全外部联接,因为它无效?
  • @bp123 :没错,最后一个查询实际上模拟了 LEFT OUTER JOIN 的行为。
  • @GMB 非常感谢,我昨晚试了运行代码,运行没有任何错误,早上一看,仍然运行。我现在取消了它,因为它是一个无限循环。我相信某处有错误,我尝试调试但无法识别。我相信这可能与列的命名有关,我更新了上面的问题以匹配单词之间的 _ 以使其更容易。请注意不同输入表的列之间的命名差异,然后输出表中的输出列应与上例中的样子相同。谢谢
【解决方案2】:

试试这个

select 
  s.ProductNumber,
  s.Region,
  sum(measureValues) Forecast,
  sum(itemValues) Sales
from MI_STAT_TOTAL m
FULL OUTER join SALES_TOTAL s
  on m.PlanningHierarcy2 = s.ProductNumber
group by
  s.ProductNumber,
  s.Region

用于插入操作

 INSERT INTO P2_Region_Unique
    select 
      s.ProductNumber,
      s.Region,
      sum(measureValues) Forecast,
      sum(itemValues) Sales
    from MI_STAT_TOTAL m
    FULL OUTER join SALES_TOTAL s
      on m.PlanningHierarcy2 = s.ProductNumber
    group by
      s.ProductNumber,
      s.Region

如果您的 MySQL 版本低于版本 8 则

select 
  s.ProductNumber,
  s.Region,
  sum(measureValues) Forecast,
  sum(itemValues) Sales
from 
(
  SELECT * from MI_STAT_TOTAL m
  LEFT join SALES_TOTAL s
    on m.PlanningHierarcy2 = s.ProductNumber
  union 
  SELECT * from MI_STAT_TOTAL m
  RIGHT JOIN SALES_TOTAL s
    on m.PlanningHierarcy2 = s.ProductNumber
)
group by
  s.ProductNumber,
  s.Region

【讨论】:

  • 谢谢@simonare。我稍微更新了问题,其中我们有一个项目存在于一个表中但不存在于另一个表中。但是在输出表中,我仍然希望看到这个结果。请检查上面的预期输出。您能否更新您的代码以反映这一点?
  • 你可以使用 FULL OUTER JOIN 代替 INNER JOIN
  • 截至 2019 年 2 月,no 版本的 MySQL 支持 FULL OUTER JOIN
  • @Nick 是的,我在使用完全外连接时遇到错误
猜你喜欢
  • 1970-01-01
  • 2023-04-02
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
  • 2019-05-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多