我增强@vkp的答案,使之更加通用的,(如果你真的很挑剔,我们需要处理的边缘情况下,第一周或最后一周的几天可以分为不同年份)
在这里,我添加了使用Datefirst设置更改一周中第一天的功能。更多DATEFIRST MSDN:https://msdn.microsoft.com/en-us/library/ms181598.aspx
/* Setup Test Data
Drop Table #T1
Create Table #T1 (UID Varchar(10), Dt Date, Hrs int)
insert into #T1 Values
('Mike' , GetDate() , 8) , -- Sat 07/23
('Mike' , GetDate()-1 , 8) ,
('Mike' , GetDate()-2 , 8) ,
('Mike' , GetDate()+3 , 8) -- Tue 07/26
('John' , GetDate() , 8) , -- Sat 07/23
('John' , GetDate()-1 , 8) ,
('John' , GetDate()-2 , 8) ,
('John' , GetDate()+3 , 8)
insert into #T1 Values
('Mike' , GetDate() - 206 , 8) , --- One Date for Last Year 12/30 to Test Edge Case
-- select * , DatePart(WEEK, Dt) from #T1
*/
- 创建一个帮助电视功能要得到某一周的日期在一年
ALTER FUNCTION GetDates
(
@WK int ,
@yr varchar(5) = ''
)
RETURNS
@Table_Var TABLE
(
DD int,
Dt Date,
Wk int
)
AS
BEGIN
IF @yr = '' SET @yr = YEAR(Getdate()) -- If Year is Blank then Default to current year
Declare @LastDateOfYr Date = RTRIM(@YR)+'-12-31' -- Last Day of the year
Declare @LastDayOfYr Int = CAST(Datename(dy, @LastDateOfYr) as int) -- No.of Days in the Year to Handle Leap Yrs
;WITH Dates as
(
-- SELECT 0 as DD , DATEADD(D, 0, @yr) as Dt , DatePart(WEEK, DATEADD(D, 0 , @yr)) as Wk
SELECT Datepart(DAYOFYEAR,DateAdd(D, (@WK-2)*7, @yr)) as DD , DATEADD(D, (@WK-2)*7, @yr) as Dt , @WK-2 as Wk -- Initial values for the Recursive CTE.
UNION ALL
SELECT Dates.DD+1 as DD , DATEADD(D, Dates.DD, @yr) , DatePart(WEEK,DATEADD(D, Dates.DD, @yr)) from Dates where Dates.DD <= @LastDayOfYr
AND Wk <= @WK + 1 -- Terminator for Recursion
)
INSERT INTO @Table_Var
SELECT
DD ,
Dt ,
Wk
FROM Dates as A
WHERE A.Wk = @WK
OPTION (MAXRECURSION 21) -- At any point we dont use CTE For more than 3 Weeks (one week actually). If the CTE is changed by using the commented out Initializer inside the CTE Above then this number has to change accordingly
RETURN
END
GO
查询:
SET DATEFIRST 1 -- Make Monday as First Day of Week. The default is Sunday.
Select B.* , A.* , ISNULL(T.Hrs,0) Hours_Worked
FROM
(SELECT Distinct UID,
DatePart(WEEK, Dt) as WK ,
DatePart(YEAR, Dt) as Yr
FROM #T1
) A
CROSS APPLY dbo.GetDates(A.WK, A.Yr) B -- Helper Function Used to apply
LEFT OUTER JOIN #T1 T ON B.Dt = T.Dt
你有一个主日期表? –