我需要在视图中显示每天的库存水平。我有一个表列出当前项目和数量,另一个表列出了这些项目发生的所有事务。我需要创建一个查询,列出趋势报告中该日期的项目,日期和库存水平。以下是表格中的一些示例数据:
产品:
ItemNumber QuantityOnHand
---------- --------------
B34233 25.0
B34234 10.0
ItemTransactions:
TransDate ItemNumber Quantity
----------- ---------- --------
1/1/2011 B34233 10.0
1/2/2011 B34234 -15.0
1/2/2011 B34233 -5.0
1/4/2011 B34234 -10.0
以下是我想从查询中获得的结果:
Date ItemNumber Quantity
---- ---------- --------
12/31/2010 B34233 20.0
12/31/2010 B34234 35.0
1/1/2011 B34233 30.0
1/1/2011 B34234 35.0
1/2/2011 B34233 25.0
1/2/2011 B34234 20.0
1/3/2011 B34233 25.0
1/3/2011 B34234 20.0
1/4/2011 B34233 25.0
1/4/2011 B34234 10.0
我该如何撰写此查询?我对TSQL非常了解,但无法想出一种编写此查询的方法。
答案 0 :(得分:1)
在SQL Server 2005
及以上:
WITH dates (itemNumber, quantity, currentDate, minDate) AS
(
SELECT itemNumber, CAST(quantityOnHand AS DECIMAL(20, 2)), it.*
FROM items i
CROSS APPLY
(
SELECT MAX(transDate) AS currentDate,
MIN(transDate) AS minDate
FROM itemTransactions it
) it
UNION ALL
SELECT d.itemNumber,
CAST
(
d.quantity -
COALESCE(
(
SELECT it.quantity
FROM itemTransactions it
WHERE it.transDate = d.currentDate
AND it.itemNumber = d.itemNumber
), 0) AS DECIMAL(20, 2)),
DATEADD(d, -1, currentDate),
minDate
FROM dates d
WHERE currentDate >= minDate
)
SELECT currentDate, itemNumber, quantity
FROM dates
ORDER BY
currentDate, itemNumber
这假设您每天每件商品有一笔交易(这是CTE
中递归SQL Server
的限制。
如果您不这样做,则应添加另一个CTE
,它会按天和项汇总交易,并使用它代替items
:
WITH itGrouped (transDate, itemNumber, quantity) AS
(
SELECT transDate, itemNumber, SUM(quantity)
FROM itemTransactions
GROUP BY
transDate, itemNumber
),
dates (itemNumber, quantity, currentDate, minDate) AS
(
SELECT itemNumber, CAST(quantityOnHand AS DECIMAL(20, 2)), it.*
FROM items i
CROSS APPLY
(
SELECT MAX(transDate) AS currentDate,
MIN(transDate) AS minDate
FROM itGrouped it
) it
UNION ALL
SELECT d.itemNumber,
CAST
(
d.quantity -
COALESCE(
(
SELECT it.quantity
FROM itGrouped it
WHERE it.transDate = d.currentDate
AND it.itemNumber = d.itemNumber
), 0) AS DECIMAL(20, 2)),
DATEADD(d, -1, currentDate),
minDate
FROM dates d
WHERE currentDate >= minDate
)
SELECT currentDate, itemNumber, quantity
FROM dates
ORDER BY
currentDate, itemNumber
答案 1 :(得分:0)
请参阅,查询很简单,但您对日期的要求是什么。我给出了一个简单的查询,它会给你一个想法,我正在使用一个临时表:
Create Table #Transection
(
ID int Identity(1,1) not null,Item_Number varchar(20),Transection_Date datetime,Quantity_Available decimal(10,2)
)
insert into #Transection (Item_Number) (Select ItemNumber from Items)
Declare @Product varchar(20),@Next_Product Cursor, @Item varchar(20),@Quantity decimal(10,2)
set @Next_Product= CURSOR FOR Select Item_Number from #Transection open @Next_Product Fetch Next from @Next_Product into @Product
While @@Fetch_Status=0
Begin
set @Item=(Select ItemNumber from ItemTransection where ItemNumber= @Product)
if is not null
Begin
Set @Quantity=(Select top 1 Items.Quantityonhand -ItemsTrasection.Quant as Quantity from Items Join
ItemsTrasection on ItemsTrasection.ItemNumber=Items.ItemNumber where ItemsTrasection.ItemNumber=@Item order by ItemsTrasection.TransDate desc)
update #Transection set Transection_Date=(Select top 1 TransDate from ItemsTrasection where ItemNumber=@Item order by TransDate desc), Quantity=@Quantity
where Item_Number=@Item
End
Else
Begin
update #Transection set Transection_Date=(Select top 1 TransDate from Items where ItemNumber=@Item ), Quantity=(Select top 1 from Items where ItemNumber=@Item )
where Item_Number=@Item
End
End
Select * from #Transection
答案 2 :(得分:0)
一个简单的版本,使用子选择来获取每天的数量。
如果你没有100k的交易和/或一个不错的sql框,这是一个好的/快速的解决方案。
请原谅凌乱的SQL(午餐时间编码:P)
CREATE TABLE #transactions (ID INT, DTE DATETIME, PROD VARCHAR(25), QTY INT )
CREATE TABLE #products (ID VARCHAR(25))
CREATE TABLE #dates (DTE DATETIME)
-- create some dates - you would do this dynamically
INSERT INTO #dates values (convert(datetime, '01/01/2011', 103))
INSERT INTO #dates values (convert(datetime, '02/01/2011', 103))
INSERT INTO #dates values (convert(datetime, '03/01/2011', 103))
-- create some products - you would get these from where-ever they live
INSERT INTO #products values ('A')
INSERT INTO #products values ('B')
-- create some transactions - you would get these from where-ever they live
INSERT INTO #transactions values (1, convert(datetime, '01/01/2011', 103), 'A', 25)
INSERT INTO #transactions values (2, convert(datetime, '01/01/2011', 103), 'A', -5)
INSERT INTO #transactions values (3, convert(datetime, '02/01/2011', 103), 'A', 60)
INSERT INTO #transactions values (4, convert(datetime, '02/01/2011', 103), 'A', -15)
INSERT INTO #transactions values (5, convert(datetime, '03/01/2011', 103), 'A', 100)
INSERT INTO #transactions values (6, convert(datetime, '03/01/2011', 103), 'A', -20)
INSERT INTO #transactions values (7, convert(datetime, '01/01/2011', 103), 'B', 10)
INSERT INTO #transactions values (8, convert(datetime, '01/01/2011', 103), 'B', 5)
INSERT INTO #transactions values (9, convert(datetime, '02/01/2011', 103), 'B', -30)
INSERT INTO #transactions values (1, convert(datetime, '02/01/2011', 103), 'B', 50)
INSERT INTO #transactions values (11, convert(datetime, '03/01/2011', 103), 'B', 10)
INSERT INTO #transactions values (12, convert(datetime, '03/01/2011', 103), 'B', 200)
-- Join dates and transactions - Do a sub select from 'begining of time' to get qty on hand per day
SELECT CONVERT(VARCHAR(25), a.DTE, 103), b.id, (SELECT sum(qty) from #transactions c where b.id = c.prod and c.DTE <= a.DTE)
FROM #dates a, #products b
-- One benefit to this approach means you can genereate qty_on_hand per days were no transactions have occured (if you needed this)
DROP TABLE #transactions
DROP TABLE #products
DROP TABLE #dates