如何计算 运行 特定日期或更早的总计?
How to calculate running total over specific date or better?
我想计算目前完成尽可能多的订单后可以完成哪些订单以及缺少哪些日期 (diff)。按 FEFO.
的顺序选取
在考虑这个问题时,我认为某种基于库存日期和订单日期的 运行 总和是一种解决方法。基于 Calculate running total / running balance 和其他类似的线程,它似乎很适合这个问题 - 但我对其他解决方案持开放态度。
示例代码
DECLARE @stockTable TABLE (
BATCH_NUM nvarchar(16),
QUANTITY int,
DATE_OUTGO DATE
)
DECLARE @orderTable TABLE (
ORDER_ID int,
QUANTITY int,
DATE_OUTGO DATE
)
INSERT INTO @stockTable (BATCH_NUM, QUANTITY, DATE_OUTGO)
VALUES
('1000', 10, '2017-08-25'),
('1001', 20, '2017-08-26'),
('1002', 10, '2017-08-27')
INSERT INTO @orderTable (ORDER_ID, QUANTITY, DATE_OUTGO)
VALUES
(1, 10, '2017-08-25'),
(1, 12, '2017-08-25'),
(2, 10, '2017-08-26'),
(3, 10, '2017-08-26'),
(4, 16, '2017-08-26')
SELECT
DATE_OUTGO,
SUM(RunningTotal) AS DIFF
FROM (
SELECT
orderTable.DATE_OUTGO AS DATE_OUTGO,
RunningTotal = SUM(stockTable.QUANTITY - orderTable.QUANTITY ) OVER
(ORDER BY stockTable.DATE_OUTGO ROWS UNBOUNDED PRECEDING)
FROM
@orderTable orderTable
INNER JOIN @stockTable stockTable
ON stockTable.DATE_OUTGO >= orderTable.DATE_OUTGO
GROUP BY
orderTable.DATE_OUTGO,
stockTable.DATE_OUTGO,
stockTable.QUANTITY,
orderTable.QUANTITY
) A
GROUP BY DATE_OUTGO
结果
The correct result would look like this.
-------------------------
| OT_DATE_OUTGO | DIFF |
-------------------------
| 2017-08-25 | 0 |
-------------------------
| 2017-08-26 | -18 |
-------------------------
My result currently looks like this.
-------------------------
| OT_DATE_OUTGO | DIFF |
-------------------------
| 2017-08-25 | 80 |
-------------------------
| 2017-08-26 | 106 |
-------------------------
我已经去掉了复杂的东西,比如物品编号,同时不同的需求(只使用确切的日期和日期或更好的日期)等,以尽可能简化核心问题。
编辑 1:
更新了表格和结果中的行(正确且使用原始查询)。
第一个答案在 2017-08-25 上给出了 -12 的差异而不是 0。但是 2017-08-26 是正确的。
您可以使用以下查询:
;WITH ORDER_RUN AS (
SELECT SUM(SUM(QUANTITY)) OVER (ORDER BY DATE_OUTGO) AS ORDER_RUNTOTAL,
DATE_OUTGO
FROM @orderTable
GROUP BY DATE_OUTGO
), STOCK_RUN AS (
SELECT SUM(SUM(QUANTITY)) OVER (ORDER BY DATE_OUTGO) AS STOCK_RUNTOTAL,
DATE_OUTGO
FROM @stockTable
GROUP BY DATE_OUTGO
)
SELECT ORR.DATE_OUTGO AS OT_DATE_OUTGO,
X.STOCK_RUNTOTAL - ORDER_RUNTOTAL AS DIFF
FROM ORDER_RUN AS ORR
OUTER APPLY (
SELECT TOP 1 STOCK_RUNTOTAL
FROM STOCK_RUN AS SR
WHERE SR.DATE_OUTGO <= ORR.DATE_OUTGO
ORDER BY SR.DATE_OUTGO DESC) AS X
第一个 CTE
计算订单总计 运行,而第二个 CTE
计算库存总计 运行。查询使用 OUTER APPLY
获取截至当前订单发出日期 的库存 运行 总计 。
编辑:
如果您想消耗与订单日期相关的未来日期的库存,则只需替换:
WHERE SR.DATE_OUTGO <= ORR.DATE_OUTGO
和
WHERE STOCK_RUNTOTAL <= ORDER_RUNTOTAL
在OUTER APPLY
操作中。
编辑 2:
下面的改进查询应该最终可以解决问题:
;WITH ORDER_RUN AS (
SELECT SUM(SUM(QUANTITY)) OVER (ORDER BY DATE_OUTGO) AS ORDER_RUNTOTAL,
DATE_OUTGO
FROM @orderTable
GROUP BY DATE_OUTGO
), STOCK_RUN AS (
SELECT SUM(SUM(QUANTITY)) OVER (ORDER BY DATE_OUTGO) AS STOCK_RUNTOTAL,
SUM(SUM(QUANTITY)) OVER () AS TOTAL_STOCK,
DATE_OUTGO
FROM @stockTable
GROUP BY DATE_OUTGO
)
SELECT ORR.DATE_OUTGO AS OT_DATE_OUTGO,
CASE
WHEN X.STOCK_RUNTOTAL - ORDER_RUNTOTAL >= 0 THEN 0
ELSE X.STOCK_RUNTOTAL - ORDER_RUNTOTAL
END AS DIFF
FROM ORDER_RUN AS ORR
OUTER APPLY (
SELECT TOP 1 STOCK_RUNTOTAL
FROM STOCK_RUN AS SR
WHERE STOCK_RUNTOTAL >= ORDER_RUNTOTAL -- Stop if stock quantity has exceeded order quantity
OR
STOCK_RUNTOTAL = TOTAL_STOCK -- Stop if the end of stock has been reached
ORDER BY SR.DATE_OUTGO) AS X
我想计算目前完成尽可能多的订单后可以完成哪些订单以及缺少哪些日期 (diff)。按 FEFO.
的顺序选取在考虑这个问题时,我认为某种基于库存日期和订单日期的 运行 总和是一种解决方法。基于 Calculate running total / running balance 和其他类似的线程,它似乎很适合这个问题 - 但我对其他解决方案持开放态度。
示例代码
DECLARE @stockTable TABLE (
BATCH_NUM nvarchar(16),
QUANTITY int,
DATE_OUTGO DATE
)
DECLARE @orderTable TABLE (
ORDER_ID int,
QUANTITY int,
DATE_OUTGO DATE
)
INSERT INTO @stockTable (BATCH_NUM, QUANTITY, DATE_OUTGO)
VALUES
('1000', 10, '2017-08-25'),
('1001', 20, '2017-08-26'),
('1002', 10, '2017-08-27')
INSERT INTO @orderTable (ORDER_ID, QUANTITY, DATE_OUTGO)
VALUES
(1, 10, '2017-08-25'),
(1, 12, '2017-08-25'),
(2, 10, '2017-08-26'),
(3, 10, '2017-08-26'),
(4, 16, '2017-08-26')
SELECT
DATE_OUTGO,
SUM(RunningTotal) AS DIFF
FROM (
SELECT
orderTable.DATE_OUTGO AS DATE_OUTGO,
RunningTotal = SUM(stockTable.QUANTITY - orderTable.QUANTITY ) OVER
(ORDER BY stockTable.DATE_OUTGO ROWS UNBOUNDED PRECEDING)
FROM
@orderTable orderTable
INNER JOIN @stockTable stockTable
ON stockTable.DATE_OUTGO >= orderTable.DATE_OUTGO
GROUP BY
orderTable.DATE_OUTGO,
stockTable.DATE_OUTGO,
stockTable.QUANTITY,
orderTable.QUANTITY
) A
GROUP BY DATE_OUTGO
结果
The correct result would look like this.
-------------------------
| OT_DATE_OUTGO | DIFF |
-------------------------
| 2017-08-25 | 0 |
-------------------------
| 2017-08-26 | -18 |
-------------------------
My result currently looks like this.
-------------------------
| OT_DATE_OUTGO | DIFF |
-------------------------
| 2017-08-25 | 80 |
-------------------------
| 2017-08-26 | 106 |
-------------------------
我已经去掉了复杂的东西,比如物品编号,同时不同的需求(只使用确切的日期和日期或更好的日期)等,以尽可能简化核心问题。
编辑 1:
更新了表格和结果中的行(正确且使用原始查询)。 第一个答案在 2017-08-25 上给出了 -12 的差异而不是 0。但是 2017-08-26 是正确的。
您可以使用以下查询:
;WITH ORDER_RUN AS (
SELECT SUM(SUM(QUANTITY)) OVER (ORDER BY DATE_OUTGO) AS ORDER_RUNTOTAL,
DATE_OUTGO
FROM @orderTable
GROUP BY DATE_OUTGO
), STOCK_RUN AS (
SELECT SUM(SUM(QUANTITY)) OVER (ORDER BY DATE_OUTGO) AS STOCK_RUNTOTAL,
DATE_OUTGO
FROM @stockTable
GROUP BY DATE_OUTGO
)
SELECT ORR.DATE_OUTGO AS OT_DATE_OUTGO,
X.STOCK_RUNTOTAL - ORDER_RUNTOTAL AS DIFF
FROM ORDER_RUN AS ORR
OUTER APPLY (
SELECT TOP 1 STOCK_RUNTOTAL
FROM STOCK_RUN AS SR
WHERE SR.DATE_OUTGO <= ORR.DATE_OUTGO
ORDER BY SR.DATE_OUTGO DESC) AS X
第一个 CTE
计算订单总计 运行,而第二个 CTE
计算库存总计 运行。查询使用 OUTER APPLY
获取截至当前订单发出日期 的库存 运行 总计 。
编辑:
如果您想消耗与订单日期相关的未来日期的库存,则只需替换:
WHERE SR.DATE_OUTGO <= ORR.DATE_OUTGO
和
WHERE STOCK_RUNTOTAL <= ORDER_RUNTOTAL
在OUTER APPLY
操作中。
编辑 2:
下面的改进查询应该最终可以解决问题:
;WITH ORDER_RUN AS (
SELECT SUM(SUM(QUANTITY)) OVER (ORDER BY DATE_OUTGO) AS ORDER_RUNTOTAL,
DATE_OUTGO
FROM @orderTable
GROUP BY DATE_OUTGO
), STOCK_RUN AS (
SELECT SUM(SUM(QUANTITY)) OVER (ORDER BY DATE_OUTGO) AS STOCK_RUNTOTAL,
SUM(SUM(QUANTITY)) OVER () AS TOTAL_STOCK,
DATE_OUTGO
FROM @stockTable
GROUP BY DATE_OUTGO
)
SELECT ORR.DATE_OUTGO AS OT_DATE_OUTGO,
CASE
WHEN X.STOCK_RUNTOTAL - ORDER_RUNTOTAL >= 0 THEN 0
ELSE X.STOCK_RUNTOTAL - ORDER_RUNTOTAL
END AS DIFF
FROM ORDER_RUN AS ORR
OUTER APPLY (
SELECT TOP 1 STOCK_RUNTOTAL
FROM STOCK_RUN AS SR
WHERE STOCK_RUNTOTAL >= ORDER_RUNTOTAL -- Stop if stock quantity has exceeded order quantity
OR
STOCK_RUNTOTAL = TOTAL_STOCK -- Stop if the end of stock has been reached
ORDER BY SR.DATE_OUTGO) AS X