基于每日库存报表编写SQL实现库存出库统计的方法
实现每日出库产品/数量报表的SQL方案
没问题!完全可以通过SQL来实现这个每日出库报表的需求,我来给你拆解思路并提供可行的查询方案。
先理清楚需求场景
你提到的两种出库情况,其实可以归纳成两类:
- 场景1:同一个
InboundID+ArticleCode的组合,第二天的库存比前一天少了,减少的数值就是出库量 - 场景2:前一天还在库存报表里的
InboundID+ArticleCode组合,第二天直接消失了,那前一天的库存总量就是全部出库的数量
我们可以用SQL Server的窗口函数(LAG)来关联连续两天的库存数据,或者用自连接的方式,这里用窗口函数会更简洁高效,适合SQL Server 2012及以后的版本。
先明确表结构
假设你的库存报表存在一个叫DailyInventory的表,结构大概是这样的(建议把Date字段设为DATE类型,别用字符串的'yesterday'/'today',日期计算会更靠谱):
CREATE TABLE DailyInventory ( ArticleCode VARCHAR(50), Description VARCHAR(100), InboundID INT, TotalStock INT, [Date] DATE );
直接上可用的SQL查询
下面这个查询可以直接用来生成当日的出库报表,我会给你拆解每个部分的作用:
WITH InventoryWithPrevDay AS ( SELECT ArticleCode, Description, InboundID, TotalStock, [Date], -- 拉取同一组合前一天的库存数量 LAG(TotalStock) OVER ( PARTITION BY ArticleCode, InboundID ORDER BY [Date] ) AS PrevDayStock, -- 拉取前一天的日期,用来确认是连续的统计日 LAG([Date]) OVER ( PARTITION BY ArticleCode, InboundID ORDER BY [Date] ) AS PrevDayDate FROM DailyInventory ) SELECT ArticleCode, Description, InboundID, -- 计算出库量:如果当天没这条记录,就用前一天的库存;否则用前一天减当天的库存 CASE WHEN TotalStock IS NULL THEN PrevDayStock ELSE PrevDayStock - TotalStock END AS Gone, -- 出库日期统一为我们要统计的当日 COALESCE([Date], DATEADD(DAY, 1, PrevDayDate)) AS [Date] FROM ( -- 先处理场景1:当日有记录,且库存比前一天少 SELECT ArticleCode, Description, InboundID, TotalStock, [Date], PrevDayStock, PrevDayDate FROM InventoryWithPrevDay WHERE [Date] = CAST(GETDATE() AS DATE) -- 锁定今日的报表数据 AND PrevDayStock IS NOT NULL -- 确保前一天有这个组合的记录 AND PrevDayStock > TotalStock -- 库存确实减少了 UNION ALL -- 再处理场景2:前一天有记录,但今日完全没了这个组合 SELECT d1.ArticleCode, d1.Description, d1.InboundID, NULL AS TotalStock, NULL AS [Date], d1.TotalStock AS PrevDayStock, d1.[Date] AS PrevDayDate FROM DailyInventory d1 LEFT JOIN DailyInventory d2 ON d1.ArticleCode = d2.ArticleCode AND d1.InboundID = d2.InboundID AND d2.[Date] = CAST(GETDATE() AS DATE) WHERE d1.[Date] = DATEADD(DAY, -1, CAST(GETDATE() AS DATE)) -- 前一天的报表数据 AND d2.ArticleCode IS NULL -- 今日找不到这个组合的记录 ) AS CombinedOutbound WHERE Gone > 0 -- 只输出确实有出库的记录 ORDER BY ArticleCode, InboundID;
对应你的样本数据验证
用你给的样本数据跑这个查询,正好能得到你想要的结果:
- 前日的
BAM131-L库存是550,今日降到500,出库50(场景1) - 前日的
BAM135-L(InboundID 53800300,库存2)今日消失,出库2(场景2)
结果会是这样:
+-------------+------------------------------+-----------+------------+-----------+ | ArticleCode | Description | InboundID | Gone | Date | +-------------+------------------------------+-----------+------------+-----------+ | BAM131-L | Jacket in piqu? Georgia L | 53800222 | 50 | today | | BAM135-L | Coat Leather Jumper L | 53800300 | 2 | today | +-------------+------------------------------+-----------+------------+-----------+
一些小提醒
- 如果你的
Date字段是字符串(比如'yesterday'),记得先转成DATE类型,比如用CASE [Date] WHEN 'yesterday' THEN DATEADD(DAY,-1,GETDATE()) WHEN 'today' THEN GETDATE() END来转换。 - 如果要统计其他日期的出库报表,把
GETDATE()换成目标日期就行,比如'2024-05-20'。 - 要是需要批量统计历史数据,可以调整
WHERE条件,覆盖多个日期范围。
内容的提问来源于stack exchange,提问作者Barnabás Kriszt
相关产品推荐
相关产品推荐

