根据 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`)
值对不是唯一的,则行的排序再次不确定。在这种情况下,您必须在提供此表达式唯一性的子查询中分组,或者另外扩展排序表达式。
我正在使用 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`)
值对不是唯一的,则行的排序再次不确定。在这种情况下,您必须在提供此表达式唯一性的子查询中分组,或者另外扩展排序表达式。