SQL 中的库存盘点

Inventory Counts in SQL

我有一个关于在 SQL Server 2008R2 中使用 T-SQL 计算停售天数的问题。所以基本上我需要一个 table 有一个项目,项目从库存中耗尽的日期,以及项目补充的日期。我正在使用的原始 table 与此相似

Item_Number | Inv_date_Change | QTY | Inventory_Change_Count
------------|-----------------|-----|-----------------------
    A1      |  2014-01-10     | 10  |  1
    A1      |  2014-01-09     | 0   |  2
    A1      |  2014-01-05     | -1  |  3
    A1      |  2014-01-03     | 10  |  4
    A1      |  2014-01-01     | 0   |  5
    B2      |  2014-01-10     | 5   |  1
    B2      |  2014-01-09     | 0   |  2
    B2      |  2014-01-05     | 1   |  2

请注意,Inv_date_Change 列是该商品库存变化的日期。我添加了 Inventory_Change_Count 列作为物品库存变化量的计数器。

另请注意,即使数量已用完(0 件或少于 0 件),商品库存仍可能发生变化

我正在寻找的最终产品是这样的:

Item_Number | Date_Exhausted | Date_Replenished
------------|----------------|-----------------
     A1     |   2014-01-05   |  2014-01-10     
     A1     |   2014-01-01   |  2014-01-03     
     B2     |   2014-01-09   |  2014-01-10     

我曾尝试使用与此类似的查询,方法是使用 Inventory_Change_Count 列将 table 重新加入自身,作为在项目耗尽时 select 的一种方式:

SELECT *
FROM Inventory a
LEFT JOIN Inventory b ON a.ITEMNMBR = b.ITEMNMBR AND a.LOCNCODE = b.LOCNCODE
        AND ((a.DTE_OUT = b.DTE_OUT - 1) 
                AND a.QTY > 0 
                AND b.QTY < 1)
        WHERE b.QTY IS NOT NULL

我对这个查询 运行 的问题是项目 A1 的第一个实例在 2014-01-05 耗尽,而不是 2014-01-09 就像这个查询 return .

我也在考虑添加逻辑以查看下一个 Inventory_Change_Count 何时为正,然后加入 Inventory_Change_Count - 1(负数的第一次出现在行中)。所以像:

join where a.QTY = when b.qty >= 1 and b.Inventory_Change_Count > a.Inventory_Change_Count then a.Inventory_Change_Count - 1o

但我不知道执行此操作的确切 SQL 语法。

这有意义吗?有什么想法吗?

提前感谢所有帮助!

select a.Item_number,a.Inv_date_Change,b.Inv_date_Change 
from Inventory a join Inventory b on a.Item_number = b.Item_Number and b.Inv_date_Change > a.Inv_date_Change 
where a.QTY <= 0 and b.QTY > 0
and not exists(select * from Inventory d where d.QTY > 0 and d.Item_Number = a.Item_Number and d.Inv_date_Change > a.Inv_date_Change and d.Inv_date_Change < b.Inv_date_Change)
and isnull((select top 1 d.QTY from Inventory d where d.Item_Number = a.Item_Number and d.Inv_date_Change < a.Inv_date_Change order by d.Inv_date_Change desc), 1) > 0

这是通过相对简单的自连接完成的。问题是原始数据中的 "noise" —— 任何数量用尽的行之前紧接着另一行也用尽数量(当然是按时间顺序)。所以第一步是提供一个没有这些行的结果集。

然后是干净数据的自连接。在 A 侧,您将拥有 qty <= 0 的所有行。在 B 侧,您需要 qty 为正的行和 A 侧日期之后的最新日期。简单。

with
Noise( Item_Number, Inv_date_Change, QTY )as(
    -- Select which rows are "noise." Noise is an exhausted row
    -- immediately preceded by another exhausted row.
    select  a.*
    from    Inventory a
    join    Inventory b
        on  b.Item_Number = a.Item_Number
        and b.Inv_date_Change =(
            select  Max( Inv_date_Change )
            from    Inventory
            where   Item_Number = a.Item_Number
                and Inv_date_Change < a.Inv_date_Change )
    where   a.qty <= 0
        and b.qty <= 0
),
Clean( Item_Number, Inv_date_Change, QTY )as(
    -- Now provide the noise-free data.
    select  r.*
    from    Inventory     r
    left join Noise n
        on  n.Item_Number = r.Item_Number
        and n.Inv_date_Change = r.Inv_date_Change
    where   n.Item_Number is null
)
select  a.Item_Number,
        a.Inv_date_Change as Date_Exhausted,
        b.Inv_date_Change as Date_Replenished
from    Clean a
join    Clean b
    on  b.Item_Number = a.Item_Number  -- Has to be the same item
    and b.Inv_date_Change =(           -- with...
        select  Min( Inv_date_Change ) -- most recent date
        from    Clean
        where   Item_Number = a.Item_Number
            and Qty > 0                               -- with non-zero quantity
            and Inv_date_Change > a.Inv_date_Change ) -- after exhaustion date
where   a.qty <= 0  -- And this is exhaustion
order by a.Item_Number, a.Inv_date_Change desc;

然后我问的问题是已经用完但还没有补充的物品怎么办?正如您在我的 Fiddle 中看到的那样,我添加了一条数据线来表示这种情况。这是通过将最终连接更改为左连接来处理的。因此,Date_Replenished 字段中的 null 表示该项目的库存目前仍然用完。