SQL,如何在 while 循环中正确求和并按周数写入 table

SQL, How to correctly sum in while loop and write it to table by weeks number

我有需要正确求和的数据,但不太清楚如何:

create table #Test
(
Job [nvarchar](20) 
,[Order] [nvarchar](20) 
,WeekNumber int
,startday date
,endday date
,WeeklyHrs decimal(17, 5)
,WhatTheClientWants decimal(17, 5)
,PreviousHrs decimal(17, 5)
)

INSERT INTO #Test
VALUES 
(1,1,1,'2022-05-09','2022-05-15',172,NULL,0),
(1,1,2,'2022-05-16','2022-05-22',9,NULL,0),
(1,2,1,'2022-05-09','2022-05-15',9,NULL,0),
(1,2,999,NULL,NULL,32.5,NULL,32.5),
(1,5,1,'2022-05-09','2022-05-15',162,NULL,0),
(1,5,2,'2022-05-16','2022-05-22',20,NULL,0),
(1,5,3,'2022-05-16','2022-05-22',0,NULL,0),
(1,6,2,'2022-05-16','2022-05-22',1,NULL,0),
(1,3,999,NULL,NULL,32.5,NULL,54)

所以客户端有两个参数,@startdate、@enddate,在这些参数之间我形成了几周。比如 09.05.2022 - 15.05.2022 - 第 1 周、16.05.2022、22.05.2022 - 第 2 周。 就靠这个,后来我分组了,但是现在,新的任务出现了。 我需要第二周的时间加上第一周的时间,第三周(可能有很多周)有第一周、第二周和第三周的时间,依此类推…… 我尝试了 Update with while 但它并没有安静地工作,然后我尝试了 Window 功能,但我做错了:

declare @MaxWeek int = (select top 1 max(WeekNumber) over (PARTITION BY job) from #Test where WeekNumber <> 999)
DECLARE @i int = 0

WHILE (@i <= @MaxWeek)
BEGIN
UPDATE #Test
set WhatTheClientWants = (select sum(FullHrs) from #Test group by Job, WeekNumber)
set @i= @i+1
END

我想可能会有某种情况,如果是第一周,它只是几个小时,但如果不是,可能会有某种总和

WHILE (@i <= @MaxWeek)
BEGIN
UPDATE #Test
set WhatTheClientWants = FullHrs from #Test where WeekNumber = @i 
set @i= @i+1
END

但是我想不通是什么情况...

它应该是什么样子:

非常感谢任何帮助!

考虑使用 window 函数来执行此操作:

SELECT testtable.*, 
    SUM(WeeklyHours) OVER (PARTITION BY [Order] ORDER BY startday ASC ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS WhatTheClientWants
FROM #test as testtable

这就是获取共享相同“分区”(或 [Order] 列值)的每组记录,按 startday 对它们进行排序,然后将它们全部加在一起直到当前行。分区内的累计和。

虽然总是很容易想到“WHILE LOOP!”作为解决方案,在几乎不需要的数据库中。在这个领域的十多年里,我只需要求助于一次 while 循环来获得一个没有基于集合的替代方案的非常程序化的解决方案。


刚刚注意到新列中 NULL startday 的空值。用 UNION ALL 破坏它就足够了:

SELECT testtable.*, 
    SUM(WeeklyHrs) OVER (PARTITION BY [Order] ORDER BY startday ASC ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS WhatTheClientWants
FROM #test as testtable
WHERE StartDay IS NOT NULL 
UNION ALL
SELECT testtable.*, NULL
FROM #test as testtable
WHERE StartDay IS NULL

JNevill 解决方案的替代方案

select Job 
,[Order] 
,WeekNumber 
,startday 
,endday 
,WeeklyHrs 
,sum(WeeklyHrs) OVER (PARTITION BY [Order] ORDER BY [Order], WeekNumber )
,PreviousHrs 
from #test

因为您似乎只在 [Order]

上进行分区

顺便说一下,这可能与您的预期结果不符 - 这些结果与您提供的数据完全不符 - 可能需要您检查其他内容