SQL Server中关联查询无结果时的库存计算问题
SQL Server中关联查询无结果时的库存计算问题
我明白你的问题啦!你的库存计算逻辑本身是对的,但现在卡在两个尴尬的场景:一是最后一次盘点后到目标日期之间没任何库存变动,关联查询直接查不到数据;二是有些产品压根没做过盘点记录,连初始库存的来源都没有。咱们一步步来解决这两个问题:
核心思路调整
咱们需要把初始库存(最后一次盘点或默认0)和后续变动的逻辑拆开,用LEFT JOIN替代原来的INNER JOIN,确保哪怕没有后续变动,初始库存的记录也能保留;同时还要处理“无盘点记录”的情况,给这类产品一个默认的初始库存0。
完整解决方案SQL
WITH LastInventory AS ( -- 第一步:找出每个产品+仓库的最后一次盘点日期 SELECT CodArt, CodAlm, MAX(FecDoc) AS LastInvDate FROM MOVSTOCKS WHERE TipDoc = 'IN' GROUP BY CodArt, CodAlm UNION ALL -- 第二步:补充没有盘点记录的产品+仓库组合,给个极早的日期(确保所有变动都能被计算) SELECT DISTINCT CodArt, CodAlm, CAST('1900-01-01' AS DATE) AS LastInvDate FROM MOVSTOCKS WHERE NOT EXISTS ( SELECT 1 FROM MOVSTOCKS inv WHERE inv.CodArt = MOVSTOCKS.CodArt AND inv.CodAlm = MOVSTOCKS.CodAlm AND inv.TipDoc = 'IN' ) ), InitialStock AS ( -- 第三步:获取对应初始库存,无盘点记录则默认0 SELECT li.CodArt, li.CodAlm, COALESCE(mv.UnidadesStock, 0) AS InitialStock, li.LastInvDate FROM LastInventory li LEFT JOIN MOVSTOCKS mv ON li.CodArt = mv.CodArt AND li.CodAlm = mv.CodAlm AND li.LastInvDate = mv.FecDoc AND mv.TipDoc = 'IN' ) -- 第四步:计算最终库存 SELECT isc.CodArt, mv.DescArt, isc.CodAlm, isc.InitialStock + COALESCE(SUM(mv.EntranStock), 0) - COALESCE(SUM(mv.SalenStock), 0) AS Stock FROM InitialStock isc LEFT JOIN MOVSTOCKS mv ON isc.CodArt = mv.CodArt AND isc.CodAlm = mv.CodAlm AND mv.FecDoc > isc.LastInvDate -- 只统计盘点后的变动 AND mv.FecDoc <= '2022-06-01' -- 目标日期 AND mv.TipDoc IN ('EN', 'SL') -- 只算入库和出库 WHERE isc.CodArt = 'C5' GROUP BY isc.CodArt, mv.DescArt, isc.CodAlm, isc.InitialStock ORDER BY isc.CodArt, isc.CodAlm;
代码解释
- LastInventory CTE:先收集所有有盘点记录的产品+仓库的最后盘点日期,再补充那些从未做过盘点的组合,给它们一个早于所有可能业务日期的初始日期,这样后续计算时能包含所有历史变动。
- InitialStock CTE:把最后盘点日期对应的库存取出来,没有盘点记录的产品直接设初始库存为0,避免空值问题。
- 主查询:用
LEFT JOIN关联初始库存和后续变动记录,哪怕没有变动,初始库存的行也会保留;用COALESCE把SUM返回的NULL转成0,确保计算结果不会变成空值。
验证你的示例数据
用你提供的数据测试这个SQL,会得到你预期的结果:
| CodArt | DescArt | CodAlm | Stock |
|---|---|---|---|
| C5 | Palet | 1 | 9 |
| C5 | Palet | 2 | 1 |
哪怕最后一次盘点后没有任何库存变动,这个查询也能正确返回初始库存值;如果某个产品没有任何盘点记录,也会从0开始计算所有入库减出库的总和。
备注:内容来源于stack exchange,提问作者antoine
相关产品推荐
相关产品推荐

