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]
上进行分区
顺便说一下,这可能与您的预期结果不符 - 这些结果与您提供的数据完全不符 - 可能需要您检查其他内容
我有需要正确求和的数据,但不太清楚如何:
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]
顺便说一下,这可能与您的预期结果不符 - 这些结果与您提供的数据完全不符 - 可能需要您检查其他内容