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
表示该项目的库存目前仍然用完。
我有一个关于在 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
表示该项目的库存目前仍然用完。