2016-07-22 312 views
-1

我有如下所示的表格,我想每週捕獲所有5周的工作日,無論員工是否工作。如果員工只工作3天,然後我想顯示的時間爲3天,他/她的工作和對2名失蹤天分配0:使用SQL計算周工作週數和排除週末的時間

UID  DT   HOURS_WORKED 
Mike  07/4/16   5 
Mike  07/5/16   8 
Mike  07/7/16   4 

這裏是這種情況下

所期望的結果
UID  DT   HOURS_WORKED 
Mike  07/4/16   5 
Mike  07/5/16   8 
Mike  06/6/16   0 
Mike  07/7/16   4 
Mike  07/8/16   0 

所以我想把0當他們跳過那一天的工作。我不想在週末表演。感謝您的幫助

select UID, DT, HOURS_WORKED from my table 
+0

你有一個主日期表? –

回答

1

我增強@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 
+0

謝謝,但這不起作用,當你有多個用戶和數字劑量不合適。 – moe

+0

@moe我做了很多修改......現在看看 – objectNotFound

+0

非常感謝,輸出查詢中的這個字段DD是什麼?我在實施它之前試圖理解它。再次感謝 – moe

1

構建日期CTE,這將在一個星期的所有日期和執行外連接此表上顯示0當員工沒有在給定平日工作。

with x as (select cast('2016-07-01' as date) dt 
      union all 
      select dateadd(dd,1,dt) from x where dt < '2016-07-31') 
select e.uid, t.dt, coalesce(e.hours_worked,0) hours_worked 
from (select * from x where datepart(dw,dt) between 2 and 6) t 
left join emp_table e on e.dt = t.dt 
+0

感謝vip,這裏最後的圓括號是什麼?從x選擇dateadd(dd,1,dt),其中dt <'2016-07-31') – moe

+0

,指示'cte'的結尾。 –