MySQL查询:如何获取包含前置计算值的表结果
SQL查询问题:按Item分区计算累计成本及上一行累计值
现有items表(按date升序排列)
| date | item | quantity | cost |
|---|---|---|---|
| 2022-12-01 | Pencil | 12 | 10.00 |
| 2022-12-02 | Pencil | 10 | 10.00 |
| 2022-12-04 | Pencil | 5 | 10.00 |
| 2022-12-06 | Eraser | 10 | 4.00 |
| 2022-12-10 | Eraser | 50 | 4.00 |
| 2022-12-15 | Eraser | 25 | 4.00 |
查询需求
- 计算
calculated_cost字段,公式为quantity * cost - 按行累加
calculated_cost得到accumulated_cost,按item分区,遇到新item时重置累加 - 获取
previous_accumulated_cost字段,值为上一行的accumulated_cost,首行填0.00,新item的首行同样填0.00
期望输出
| date | item | quantity | cost | calculated_cost | accumulated_cost | previous_accumulated_cost |
|---|---|---|---|---|---|---|
| 2022-12-01 | Pencil | 12 | 10.00 | 120.00 | 120.00 | 0.00 |
| 2022-12-02 | Pencil | 10 | 10.00 | 100.00 | 220.00 | 120.00 |
| 2022-12-04 | Pencil | 5 | 10.00 | 50.00 | 270.00 | 220.00 |
| 2022-12-06 | Eraser | 10 | 4.00 | 40.00 | 40.00 | 0.00 |
| 2022-12-10 | Eraser | 50 | 4.00 | 200.00 | 240.00 | 40.00 |
| 2022-12-15 | Eraser | 25 | 4.00 | 100.00 | 340.00 | 240.00 |
尝试的错误SQL
SELECT *, (i.quantity * i.cost) AS calculated_cost, SUM(i.quantity * i.cost) OVER (PARTITION BY i.item ORDER BY i.date) AS accumulated_cost, IFNULL(LAG(i2.accumulated_cost) OVER (PARTITION BY i.item ORDER BY i.date), 0) AS previous_accumulated_cost FROM items i LEFT JOIN ( SELECT item, SUM(quantity * cost) OVER (PARTITION BY item ORDER BY date) AS accumulated_cost FROM items ) i2 ON i.item = i2.item
问题原因及解决方案
你的SQL错误在于使用了不必要的JOIN,导致i2.accumulated_cost会和原表每行匹配所有同item的累加值,而非对应行的累加值。正确的做法是直接基于窗口函数计算的结果获取上一行值,无需额外JOIN。
正确SQL查询(简洁子查询版)
SELECT *, IFNULL(LAG(accumulated_cost) OVER (PARTITION BY item ORDER BY date), 0.00) AS previous_accumulated_cost FROM ( SELECT date, item, quantity, cost, quantity * cost AS calculated_cost, SUM(quantity * cost) OVER (PARTITION BY item ORDER BY date) AS accumulated_cost FROM items ) AS temp ORDER BY date;
说明
- 子查询先计算出
calculated_cost和分区累加的accumulated_cost,逻辑清晰易读 - 外部查询使用
LAG()窗口函数,按item分区、date排序,直接获取上一行的accumulated_cost - 用
IFNULL()将每个分区的首行previous_accumulated_cost替换为0.00 - 最终按
date排序保证结果顺序和原表一致
内容的提问来源于stack exchange,提问作者lyracarat03
相关产品推荐
相关产品推荐

