SQL 使用 while 循环计算多个元素的值
SQL using while loop to calculate values for multiple elements
我正在尝试使用 Ms SQL 计算仓库中每件商品的平均每日库存。
每个进出数量都记录在同一列中,我们将其命名为[数量]。由于这种结构,我判断今天库存水平的唯一方法是简单地 将时间开始时的所有数量相加 。
即
SELECT [item], SUM(quantity)
FROM item_table
如果我想查看昨天的库存水平,我需要以下代码:
SELECT [item], SUM(quantity)
FROM item_table
WHERE [date] < DATEADD(day,-1,GETDATE())
每一天依此类推。当然,我不会为了获得全年的库存水平而手动更改 DATEADD
数字 360 次。因此,我使用如下的 While 循环:
DECLARE @intFlag INT
DECLARE @s DECIMAL = 0
DECLARE @i varchar(20) --replaced with table (see table part below)
SET @intFlag = 0
WHILE (@intFlag <= 360)
BEGIN
SET @intFlag = @intFlag + 1
SET @i = (SELECT TOP (1) [item] FROM item_table ) --replaced with table (see table part below)
SET @s = (
SELECT
SUM(quantity) + @s AS inventory
FROM item_table
WHERE
item IN (@i) --replaced with table (see table part below)
AND [Date] < dateadd(day, - @intFlag, GETDATE())
)
IF @intFlag = 360
BREAK;
END
SELECT
@i AS [item],
@s/360 AS [AVG_stock]
目前为止一切正常,但我在尝试对多个项目执行相同操作时卡住了。
当我尝试用这样的 table 替换 @i
参数时:
DECLARE @items table (number varchar (20))
INSERT INTO @items
SELECT DISTINCT [Item]
FROM items_table
并尝试在
中调用它
SET @s = (
SELECT
SUM(quantity) + @s AS inventory
FROM item_table
WHERE
item IN (@items)
AND [Date] < dateadd(day, - @intFlag, GETDATE())
)
SQL 找不到 @item
table 并说需要先声明它。在这一点上,我不知道为什么会这样,我该如何解决。此外,我对该查询的性能表示怀疑,因为我将对大约 30,000 件商品执行库存计算。
也许这个问题有一个简单的解决办法,或者也许有人可以想出一种完全不同的方法来计算那该死的东西。无论如何,我可以使用我能得到的任何帮助。
亲切的问候。
你要的是累加和。即使在 SQL Server 2008 中,您的 while
循环也不是最佳方法。您不妨执行以下操作:
SELECT it.item, it2.quantity
FROM item_table it OUTER APPLY
(SELECT SUM(it2.quantity) as quantity
FROM it2
WHERE it2.item = it.item AND
it2.date < it.date
) it2;
在这种情况下,最快的方法(除了升级 SQL 服务器之外)是执行一个 while
循环,每天保持一个 增量 值.但是,这可能具有挑战性,因为您需要为每个项目处理一个单独的变量。
对于所有项目,试试这个:
With Ints(aInt) As
(Select -365 Union All
Select aInt + 1 From Ints
Where aInt < 0)
Select item,
DateAdd(day, i.aInt, getdate()) tdate
Sum(quantity) runningTotal
from item_table it join Ints i
on it.[Date] < DateAdd(day, i.aInt, getdate())
group by item, DateAdd(day, i.aInt, getdate())
Option (MaxRecursion 1000)
要将其限制为一些小的项目集,只需添加一个 where 子句
With Ints(aInt) As
(Select -365 Union All
Select aInt + 1 From Ints
Where aInt < 0)
Select item,
DateAdd(day, i.aInt, getdate()) tdate
Sum(quantity) runningTotal
from item_table it join Ints i
on it.[Date] < DateAdd(day, i.aInt, getdate())
where item in ([set of comma-delimited item values here])
group by item, DateAdd(day, i.aInt, getdate())
Option (MaxRecursion 1000)
创建一个"Numbers"(或"Tally"table)。它只是一个 single-column table 比包含顺序整数。您可以阅读有关如何创建一个 here 的信息。它们对于替换 while 循环很有用。
一旦你有了它,你就可以做这样的事情:
select i.item,
i.date,
sum(i.quantity) over (partition by i.item order by i.date) quantity
from item_table i
join Numbers n on i.date = DATEADD(dd, -1*n.n, convert(date, getdate()))
where n.n <= 365
这应该会给您 运行 每天的总数量。
我正在尝试使用 Ms SQL 计算仓库中每件商品的平均每日库存。 每个进出数量都记录在同一列中,我们将其命名为[数量]。由于这种结构,我判断今天库存水平的唯一方法是简单地 将时间开始时的所有数量相加 。 即
SELECT [item], SUM(quantity)
FROM item_table
如果我想查看昨天的库存水平,我需要以下代码:
SELECT [item], SUM(quantity)
FROM item_table
WHERE [date] < DATEADD(day,-1,GETDATE())
每一天依此类推。当然,我不会为了获得全年的库存水平而手动更改 DATEADD
数字 360 次。因此,我使用如下的 While 循环:
DECLARE @intFlag INT
DECLARE @s DECIMAL = 0
DECLARE @i varchar(20) --replaced with table (see table part below)
SET @intFlag = 0
WHILE (@intFlag <= 360)
BEGIN
SET @intFlag = @intFlag + 1
SET @i = (SELECT TOP (1) [item] FROM item_table ) --replaced with table (see table part below)
SET @s = (
SELECT
SUM(quantity) + @s AS inventory
FROM item_table
WHERE
item IN (@i) --replaced with table (see table part below)
AND [Date] < dateadd(day, - @intFlag, GETDATE())
)
IF @intFlag = 360
BREAK;
END
SELECT
@i AS [item],
@s/360 AS [AVG_stock]
目前为止一切正常,但我在尝试对多个项目执行相同操作时卡住了。
当我尝试用这样的 table 替换 @i
参数时:
DECLARE @items table (number varchar (20))
INSERT INTO @items
SELECT DISTINCT [Item]
FROM items_table
并尝试在
中调用它SET @s = (
SELECT
SUM(quantity) + @s AS inventory
FROM item_table
WHERE
item IN (@items)
AND [Date] < dateadd(day, - @intFlag, GETDATE())
)
SQL 找不到 @item
table 并说需要先声明它。在这一点上,我不知道为什么会这样,我该如何解决。此外,我对该查询的性能表示怀疑,因为我将对大约 30,000 件商品执行库存计算。
也许这个问题有一个简单的解决办法,或者也许有人可以想出一种完全不同的方法来计算那该死的东西。无论如何,我可以使用我能得到的任何帮助。
亲切的问候。
你要的是累加和。即使在 SQL Server 2008 中,您的 while
循环也不是最佳方法。您不妨执行以下操作:
SELECT it.item, it2.quantity
FROM item_table it OUTER APPLY
(SELECT SUM(it2.quantity) as quantity
FROM it2
WHERE it2.item = it.item AND
it2.date < it.date
) it2;
在这种情况下,最快的方法(除了升级 SQL 服务器之外)是执行一个 while
循环,每天保持一个 增量 值.但是,这可能具有挑战性,因为您需要为每个项目处理一个单独的变量。
对于所有项目,试试这个:
With Ints(aInt) As
(Select -365 Union All
Select aInt + 1 From Ints
Where aInt < 0)
Select item,
DateAdd(day, i.aInt, getdate()) tdate
Sum(quantity) runningTotal
from item_table it join Ints i
on it.[Date] < DateAdd(day, i.aInt, getdate())
group by item, DateAdd(day, i.aInt, getdate())
Option (MaxRecursion 1000)
要将其限制为一些小的项目集,只需添加一个 where 子句
With Ints(aInt) As
(Select -365 Union All
Select aInt + 1 From Ints
Where aInt < 0)
Select item,
DateAdd(day, i.aInt, getdate()) tdate
Sum(quantity) runningTotal
from item_table it join Ints i
on it.[Date] < DateAdd(day, i.aInt, getdate())
where item in ([set of comma-delimited item values here])
group by item, DateAdd(day, i.aInt, getdate())
Option (MaxRecursion 1000)
创建一个"Numbers"(或"Tally"table)。它只是一个 single-column table 比包含顺序整数。您可以阅读有关如何创建一个 here 的信息。它们对于替换 while 循环很有用。
一旦你有了它,你就可以做这样的事情:
select i.item,
i.date,
sum(i.quantity) over (partition by i.item order by i.date) quantity
from item_table i
join Numbers n on i.date = DATEADD(dd, -1*n.n, convert(date, getdate()))
where n.n <= 365
这应该会给您 运行 每天的总数量。