我有一个包含 4 列的表:Project、ScenarioStart、ScenarioEnd 和 TimePeriods。
TimePeriods 一开始总是空白,因为这是我需要填充项目所有适用时间段的字符串(包括开始和结束)。
所有时间段的格式均为 yyyyMm
例如
Project ScenarioStart ScenarioEnd TimePeriods
1 2024M9 2025M3
2 2024M6 2024M10
我现在需要的是使用包含每行所有适用期间的文本字符串来更新表。 (我正在使用管道分离)
所以第 1 行将是 '2024M9|2024M10|2024M11|2024M12|2025M1|2025M2|2025M3'
第 2 行应为“2024M6|2024M7|2024M8|2024M9|2024M10”
我已经有一个生成字符串的工作代码,但它有两个问题:
生成字符串的代码如下。 有人可以帮我将其转换为表中每一行的更新吗?
-- Create the variables to hold Start- and End-Period, and the blank Period List --
-- Currently only works if hard-coded, but should read the table cells)
declare @sScenarioStart nvarchar(10) = '2024M1',
@sScenarioEnd nvarchar(10) = '2026M3',
@SplitPeriods nvarchar(max) = ''
----------------------------------------------------------------
-- Create a list of valid time references for this submission --
----------------------------------------------------------------
Declare @sCounterTime nvarchar(10) = @sScenarioStart,
@sCounterYear nvarchar(4) = substring(@sScenarioStart,1,4),
@sCounterMonth nvarchar(4) = substring(@sScenarioStart,6,len(@sScenarioStart)-5)
print 'Counter Time: ' + @sCounterTime + 'Counter Year: ' + @sCounterYear + 'Counter Month: ' + @sCounterMonth
-- Generate the comma-sparated list of time periods --
While @sCounterTime <> @sScenarioEnd
BEGIN
-- Add the initial Time Period to the output string
set @SplitPeriods = @SplitPeriods + @sCounterTime + '|'
-- If Current month is December then +1 the year and reset the month back to 1
set @sCounterYear = case @sCounterMonth
when 12 then @sCounterYear + 1
else @sCounterYear
end
set @sCounterMonth = case @sCounterMonth
when 12 then 1
else @sCounterMonth + 1
end
-- Move the Time Period forward
set @sCounterTime = @sCounterYear + 'M' + @sCounterMonth
END -- End of BEGIN statement
-- Add the final Time Period to the string
set @SplitPeriods = @SplitPeriods + @sCounterTime
-- TESTING: Output the final string
print 'Final Period String: ' + @SplitPeriods
该脚本的输出是:
计数器时间:2024M1计数器年份:2024计数器月份:1
最终周期字符串:2024M1|2024M2|2024M3|2024M4|2024M5|2024M6|2024M7|2024M8|2024M9|2024M10|2024M11|2024M12|2025M1|2025M2|2025M3|2025M4 |2025M5|2025M6|2025M7|2025M8|2025M9|2025M10|2025M11 |2025M12|2026M1|2026M2|2026M3
这两个输出都是正确的,但需要在每一行的 TimePeriods 列中更新第二个输出。
谢谢
CREATE TABLE Example
(
Project VARCHAR(512),
ScenarioStart VARCHAR(512),
ScenarioEnd VARCHAR(512),
TimePeriods VARCHAR(512)
);
INSERT INTO Example (Project, ScenarioStart, ScenarioEnd) VALUES
('1', '2024M9', '2025M3'),
('2', '2024M6', '2024M10');
SELECT * FROM Example;
-- Recursive CTE to generate a list of months within the date range:
WITH Months AS (
SELECT Example.Project, Example.ScenarioStart, Example.ScenarioEnd, CONVERT(DATE, DATEADD(D, -(DAY(CONVERT(Date, Substring(ScenarioStart,1,4) + '-' + Substring(ScenarioStart,6,2) + '-1'))) + 1, CONVERT(Date, Substring(ScenarioStart,1,4) + '-' + Substring(ScenarioStart,6,2) + '-1'))) [MonthDate]
FROM Example
UNION ALL
SELECT Example.Project, Example.ScenarioStart, Example.ScenarioEnd, DATEADD(M, 1, MonthDate)
FROM Months
INNER JOIN Example on Example.Project=Months.Project
WHERE MonthDate <= DATEADD(M, -1, CONVERT(Date,Substring(Example.ScenarioEnd,1,4) + '-' + Substring(Example.ScenarioEnd,6,2) + '-1'))
)
UPDATE Example
SET Example.TimePeriods=t.TimePeriods
FROM Example E
INNER JOIN
(
SELECT Project, STRING_AGG(CAST(Year(MONTHDATE) as Varchar(4))+'M'+Cast(Month(Monthdate) as varchar(2)), '|') as TimePeriods
FROM Months
GROUP BY Project
) t
ON E.Project=t.Project
SELECT * FROM Example;
项目 | 场景开始 | 场景结束 | 时间段 |
---|---|---|---|
1 | 2024M9 | 2025M3 | 2024M9│2024M10│2024M11│2024M12│2025M1│2025M2│2025M3 |
2 | 2024M6 | 2024M10 | 2024M6│2024M7│2024M8│2024M9│2024M10 |