根据 MySQL 中的唯一项目获取累计总和

Get cumulative sum based on unique item in MySQL

我正在使用 MySQL,我正在尝试编写一个存储过程查询,该查询连接两个 table 并生成特定列的 运行 总和。而不是通常的连续 运行ning 总和是连续的,我想要每次项目更改时重置的总和。

我希望我的请求在我的可重现样本之后更加清晰。

Table 1

CREATE TABLE `table1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `Date` date DEFAULT NULL,
  `Item` varchar(20) DEFAULT NULL,
  `Quantity` decimal(5,3) DEFAULT NULL,
  `Volume` decimal(20,2) DEFAULT NULL,
  PRIMARY KEY (`id`)
  );
  
  INSERT INTO table1 (Date, Item, Quantity, Volume)
  VALUES ('2022-04-25', 'Ball', 5, 30),
        ('2022-04-25', 'Balloon', 3, 14),
        ('2022-04-25', 'Bag', 2, 7),
        ('2022-04-24', 'Ball', 7, 20),
        ('2022-04-24', 'Balloon', 1, 9),
        ('2022-04-24', 'Bag', 4, 18),
        ('2022-04-23', 'Ball', 9, 53),
        ('2022-04-23', 'Balloon', 4, 25),
        ('2022-04-23', 'Bag', 11, 12),
        ('2022-04-22', 'Ball', 13, 8);

Table 2

CREATE TABLE `table2` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `Date` date DEFAULT NULL,
  `Item` varchar(20) DEFAULT NULL,
  `Size (inches)` decimal(10,2) DEFAULT NULL,
  `density` decimal(10,2) DEFAULT NULL,
  PRIMARY KEY (`id`)
  );
  
  
  
  INSERT INTO table2 (Date, Item, `Size (inches)`, density)
  VALUES ('2022-04-25', 'Ball', 15, 20),
        ('2022-04-25', 'Balloon', 13, 34),
        ('2022-04-25', 'Bag', 12, 17),
        ('2022-04-24', 'Ball', 17, 50),
        ('2022-04-24', 'Balloon', 11, 19),
        ('2022-04-24', 'Bag', 14, 8),
        ('2022-04-23', 'Ball', 19, 3),
        ('2022-04-23', 'Balloon', 14, 5),
        ('2022-04-23', 'Bag', 31, 2),
        ('2022-04-22', 'Ball', 42, 18);

这是我目前的存储过程:

DELIMITER $$
CREATE DEFINER=`localhost`@`%` PROCEDURE `procedure1`()
BEGIN

DROP TABLE IF EXISTS `procedure_table`;

SET @running_total:=0;

CREATE TABLE `procedure_table` AS SELECT * FROM (
SELECT i.`Item`,
i.`Date`,
ROUND(i.`Volume`/i.`Size (inches)`,2) as `Volume/Size`,
ROUND(i.`Quantity`/i.`Volume`,2) as `Quantity x Volume`,
i.`Size (inches)` as `Size (inches)`,
i.`density` as density,
i.`Quantity`,
ROUND(i.Volume) as `Oil Volume`,
(@running_total := @running_total + IFNULL(i.`Volume`,0)) AS `Cumulative Volume`
FROM (SELECT `table1`.*,
`table2`.`Size (inches)`,
`table2`.`density`
  FROM `table1` 
  LEFT JOIN `table2`
  ON `table1`.Item = `table2`.`Item` 
  AND Month(`table1`.Date) = Month(`table2`.Date)
  AND Year(`table1`.Date) = Year(`table2`.Date)
  ORDER BY `table1`.Item,Date) as i) u;



END$$
DELIMITER ;

当我 运行 时,我得到一个 table 看起来像这样:

当我想要的是:

我已经尝试了 PARTITION BY 功能,但无法在 MySQL 中使用它。

如何获得我想要的输出?

编辑 - 输出没有问题的列

SELECT * FROM (
SELECT i.`Item`,
i.`Date`,
ROUND(i.`Volume`/i.`Size (inches)`,2) as `Volume/Size`,
ROUND(i.`Quantity`/i.`Volume`,2) as `Quantity x Volume`,
i.`Size (inches)` as `Size (inches)`,
i.`density` as density,
i.`Quantity`,
ROUND(i.Volume) as `Oil Volume`
FROM (SELECT `table1`.*,
`table2`.`Size (inches)`,
`table2`.`density`
  FROM `table1` 
  LEFT JOIN `table2`
  ON `table1`.Item = `table2`.`Item` 
  AND Month(`table1`.Date) = Month(`table2`.Date)
  AND Year(`table1`.Date) = Year(`table2`.Date)
  ORDER BY `table1`.Item,Date) as i) u 
  ORDER BY Item;

Output without problematic column

SELECT * 
FROM ( SELECT i.`Item`,
              i.`Date`,
              ROUND(i.`Volume`/i.`Size (inches)`,2) as `Volume/Size`,
              ROUND(i.`Quantity`/i.`Volume`,2) as `Quantity x Volume`,
              i.`Size (inches)` as `Size (inches)`,
              i.`density` as density,
              i.`Quantity`,
              ROUND(i.Volume) as `Oil Volume`
       FROM ( SELECT `table1`.*,
                     `table2`.`Size (inches)`,
                     `table2`.`density`
              FROM `table1` 
              LEFT JOIN `table2` ON `table1`.Item = `table2`.`Item` 
                                AND Month(`table1`.Date) = Month(`table2`.Date)
                                AND Year(`table1`.Date) = Year(`table2`.Date)
              ORDER BY `table1`.Item,Date
             ) as i
      ) u 
ORDER BY Item;

顺序不确定。查看您想要的输出,我看到二次排序是由 Date 输出列执行的。 IE。为了正确的输出行排序和累计总和计算,ORDER BY 必须扩展为 ORDER BY Item, `Date`;.

查询将是:

SELECT *,
       @sum := CASE WHEN Item = @item
                    THEN @sum + ROUND(i.Volume)
                    ELSE ROUND(i.Volume)
                    END AS `cumulative sum`,
       @item := Item AS Item
FROM ( SELECT i.`Item`,
              i.`Date`,
              ROUND(i.`Volume`/i.`Size (inches)`,2) as `Volume/Size`,
              ROUND(i.`Quantity`/i.`Volume`,2) as `Quantity x Volume`,
              i.`Size (inches)` as `Size (inches)`,
              i.`density` as density,
              i.`Quantity`,
              ROUND(i.Volume) as `Oil Volume`
       FROM ( SELECT `table1`.*,
                     `table2`.`Size (inches)`,
                     `table2`.`density`
              FROM `table1` 
              LEFT JOIN `table2` ON `table1`.Item = `table2`.`Item` 
                                AND Month(`table1`.Date) = Month(`table2`.Date)
                                AND Year(`table1`.Date) = Year(`table2`.Date)
              ORDER BY `table1`.Item,Date
             ) as i
      ) u 
CROSS JOIN ( SELECT @item := '', @sum:=0 ) init_variables
ORDER BY Item, `Date`;

第一个附加列要么将当前 Oil Volume 添加到前一列,要么采用当前仅取决于该项目是否与前一行相同的事实。第二个附加列仅存储当前 Item 值以用于下一行评估。这些列可以在输出字段集中移动,但必须存储它们的相对位置。

PS。如果 (Item, `Date`) 值对不是唯一的,则行的排序再次不确定。在这种情况下,您必须在提供此表达式唯一性的子查询中分组,或者另外扩展排序表达式。