需求:輸入任一日期(如 2007-09-01),列出該月份按週劃分的日期區間(週日~週六),跨月週數正確處理首尾週。以下為完整 T-SQL 腳本,可直接執行或封裝為函數/預存程序。
declare @i int; -- 計數器
declare @curWk int; -- 指定日期所在年週數
declare @fstWk int; -- 該月 1 號所在年週數
declare @fstDay nvarchar(10); -- 該月第一天
declare @lstDay nvarchar(10); -- 該月最後一天
declare @tmpDay smalldatetime; -- 當前週日
declare @date smalldatetime; -- 輸入日期
declare @tmpDay1 smalldatetime; -- 當前週六
set @date = '2007-09-01'; -- 測試日期,可改為參數
-- 計算該月第一天
select @fstDay = convert(nvarchar(10), cast(cast(year(@date) as nvarchar(4)) + '-' + cast(month(@date) as nvarchar(2)) + '-01' as smalldatetime), 120);
set @fstWk = datepart(wk, @fstDay);
-- 計算該月最後一天
set @lstDay = convert(nvarchar(10), dateadd(d, -1, dateadd(m, 1, @fstDay)), 120);
-- 找出第一個屬於「本月」的週日(跳過屬於上個月的週數)
set @i = 0;
while (@i < 8)
begin
set @tmpDay = dateadd(dd, @i, @fstDay);
set @curWk = datepart(wk, @tmpDay);
if @curWk > @fstWk break;
set @i = @i + 1;
end
-- 輸出各週區間
set @i = 1;
while (@i < 7)
begin
if @i = 1
begin
-- 第 1 週:從 1 號到第一個週日前一天
print('第' + str(@i) + '週:' + @fstDay + '--------' + convert(nvarchar(10), dateadd(d, -1, @tmpDay), 120));
set @i = @i + 1;
end
if datediff(d, @tmpDay, @lstDay) >= 0
begin
set @tmpDay1 = dateadd(d, 6, @tmpDay); -- 週六 = 週日 + 6
if datediff(d, @lstDay, @tmpDay1) > 0
-- 週六超過月底,輸出 週日~月底
print('第' + str(@i) + '週:' + convert(nvarchar(10), @tmpDay, 120) + '--------' + @lstDay);
else
-- 正常週日~週六
print('第' + str(@i) + '週:' + convert(nvarchar(10), @tmpDay, 120) + '--------' + convert(nvarchar(10), @tmpDay1, 120));
end
set @tmpDay = dateadd(d, 7, @tmpDay); -- 下一個週日
if datediff(d, @tmpDay, @lstDay) < 0 break; -- 週日已超過月底,結束
set @i = @i + 1;
end
第1週:2007-09-01--------2007-09-01
第2週:2007-09-02--------2007-09-08
第3週:2007-09-09--------2007-09-15
第4週:2007-09-16--------2007-09-22
第5週:2007-09-23--------2007-09-29
第6週:2007-09-30--------2007-09-30
fn_GetMonthWeeks(@date) 回傳表值函數,供應用層直接 SELECT * FROM fn_GetMonthWeeks('2024-01-15')。