希望为两班制(蓝队/红队)的员工模型生成一个动态日历,这些日历为4天/ 4天。我希望能够根据静态日期捕获未来日期和过去日期。
例如,如果Blue团队的第一天是2016年6月1日,最后一天是2016年6月4日,那么Red团队的第一天就是2016年6月5日和最后一天是2016年6月8日,我如何创建一个在SQL Server中向前和向后看的滚动视图?
基本上我想知道哪一支队伍应该在某一天工作,这将允许我计算人员配置百分比,以查看谁出去度假/生病等。如果我可以建立滚动日历视图,我可以将其用作衡量员工绩效的驱动因素。
理想情况下,我想动态生成此视图:
示例输出:
Shift | Date
Blue | 5/24/2016 06:00:00 AM
Blue | 5/25/2016 06:00:00 AM
Blue | 5/26/2016 06:00:00 AM
Blue | 5/27/2016 06:00:00 AM
Red | 5/28/2016 06:00:00 AM
Red | 5/29/2016 06:00:00 AM
Red | 5/30/2016 06:00:00 AM
Red | 5/31/2016 06:00:00 AM
Blue | 6/1/2016 06:00:00 AM
Blue | 6/2/2016 06:00:00 AM
Blue | 6/3/2016 06:00:00 AM
Blue | 6/4/2016 06:00:00 AM
Red | 6/5/2016 06:00:00 AM
Red | 6/6/2016 06:00:00 AM
Red | 6/7/2016 06:00:00 AM
Red | 6/8/2016 06:00:00 AM
Blue | 6/9/2016 06:00:00 AM
Blue | 6/10/2016 06:00:00 AM
Blue | 6/11/2016 06:00:00 AM
Blue | 6/12/2016 06:00:00 AM
Red | etc...
提前感谢任何建议。
更新:
利用link的代码
我能够制作出滚动的未来日期:
; with samples as
(
-- start with 6/1/2016
select cast( '06-01-2016 06:00' as datetime ) as sample
union all
-- add days up to the desired end date
select dateadd( day, 1, sample )
from samples
where sample <= '2020-12-31'
),
extendedsamples as
(
-- calculate the number of days since the beginning of the first shift on 6/1/2016.
select
sample, datediff( day, '06-01-2016 06:00', sample ) as days
from samples
),
shifts as
(
-- calculate the shifts for each day.
select
*,
case when ( days + 1 ) % 8 between 1 and 4 then 'Blue' else 'Red' end as shifts
from extendedsamples
)
select
shifts,
sample
from
shifts
option (maxrecursion 0)
我现在需要弄清楚如何为这段代码制作历史作品,以便我可以捕捉以前的人员编制百分比......
更新2:
所以看起来如果我只是将一些函数和数字反转并默认为Blue team的静态转换6/1/2016前一天。我也能够产生历史性的观点。
; with samples as
(
-- start with 5/31/2016 to pull historical.
select cast( '05-31-2016 06:00' as datetime ) as sample
union all
-- subtract days back to the desired start date.
select dateadd( day, -1, sample )
from samples
where sample >= '2015-01-01'
),
extendedsamples as
(
-- calculate the number of days before the beginning of the first blue shift on 6/1/2016.
select sample, datediff( day, '05-31-2016 06:00', sample ) as days
from samples
),
shifts as
(
-- calculate the shifts for each day.
select
*,
case when ( days - 1 ) % 8 between -4 and -1 then 'Red' else 'Blue' end as shifts
from extendedsamples
)
select
shifts,
sample
from
shifts
option (maxrecursion 0)
我现在可以将这些结果转储到静态表中以供参考。有更好的解决方法吗?如果没有,我会继续这样做,并将此问题标记为已回答。
答案 0 :(得分:0)
;WITH cteDates AS (
--put in your desired start date
SELECT CAST('5/1/2016 06:00:00 AM' AS DATETIME) AS StartDate
UNION ALL
SELECT
StartDate + 1 AS StartDate
FROM
cteDates
WHERE
StartDate + 1 <= '6/30/2016 06:00:00 AM'
--put in your desired end date
)
SELECT
*
,CASE
--just use the beginning day of your known blue shift
WHEN DATEDIFF(day,'6/1/2016 06:00:00 AM',StartDate) % 8 BETWEEN -4 AND -1 THEN 'Red'
WHEN StartDate <= '6/1/2016 06:00:00 AM' THEN 'Blue'
WHEN (ABS(DATEDIFF(day,'6/1/2016 06:00:00 AM',StartDate)) + 1) % 8 BETWEEN 1 AND 4 THEN 'Blue'
ELSE 'Red'
END AS TeamShift
FROM
cteDates d
在另一个答案中,Row_Number可能有一些方法,但您需要知道该类型方法最早工作时的起始班次。但是,您可以使用递归cte轻松生成自己的日期表,然后将已经使用的公式调整为case语句。诀窍在于,在2016年6月6日向前计数时,您需要第1天到第4天蓝色但向后计数-4到-1将是红色,因此您必须考虑使用案例陈述的逻辑转换。这也是row_number下降区域之一。
答案 1 :(得分:0)
@Matt指出我错过了一个主要要求。在UDF的帮助下生成动态日期范围(下面列出)和“锚定日期”,方法并不是那么糟糕。
我已经测试了未来和过去的随机日期,结果似乎有效 真。
Declare @StartDate DateTime = '2016-07-15 06:00:00'
Declare @EndDate DateTime = '2017-12-31 06:00:00'
Declare @AnchorDate DateTime = '2016-06-01 06:00:00'
;with cteBasePos as (Select Date = RetVal,NegRowNr=0,PosRowNr = Row_Number() over (Order By RetVal Asc ) From [dbo].[udf-Create-Range-Date](@AnchorDate,@EndDate ,'DD',1) Where @EndDate >@AnchorDate)
,cteBaseNeg as (Select Date = RetVal,NegRowNr = Row_Number() over (Order By RetVal Desc)-1,PosRowNr=0 From [dbo].[udf-Create-Range-Date](@StartDate ,@AnchorDate,'DD',1) Where @StartDate<@AnchorDate)
Select Date
,Shift = IIF(((RowNr-1)/4) % 2 = 0 ,'Blue','Red')
From (
Select Date,RowNr=NegRowNr+4 from cteBaseNeg Where NegRowNr>0
Union All
Select Date,RowNr=PosRowNr+0 from cteBasePos
) A
Where Date Between @StartDate and DateAdd(DD,1,@EndDate)
Order By Date
返回
Date Shift
2016-05-22 06:00:00.000 Red
2016-05-23 06:00:00.000 Red
2016-05-24 06:00:00.000 Blue
2016-05-25 06:00:00.000 Blue
2016-05-26 06:00:00.000 Blue
2016-05-27 06:00:00.000 Blue
2016-05-28 06:00:00.000 Red
2016-05-29 06:00:00.000 Red
2016-05-30 06:00:00.000 Red
2016-05-31 06:00:00.000 Red
2016-06-01 06:00:00.000 Blue -- Anchor Date
2016-06-02 06:00:00.000 Blue
2016-06-03 06:00:00.000 Blue
2016-06-04 06:00:00.000 Blue
2016-06-05 06:00:00.000 Red
2016-06-06 06:00:00.000 Red
2016-06-07 06:00:00.000 Red
2016-06-08 06:00:00.000 Red
2016-06-09 06:00:00.000 Blue
2016-06-10 06:00:00.000 Blue
2016-06-11 06:00:00.000 Blue
2016-06-12 06:00:00.000 Blue
2016-06-13 06:00:00.000 Red
2016-06-14 06:00:00.000 Red
2016-06-15 06:00:00.000 Red
2016-06-16 06:00:00.000 Red
2016-06-17 06:00:00.000 Blue
2016-06-18 06:00:00.000 Blue
2016-06-19 06:00:00.000 Blue
2016-06-20 06:00:00.000 Blue
2016-06-21 06:00:00.000 Red
2016-06-22 06:00:00.000 Red
2016-06-23 06:00:00.000 Red
2016-06-24 06:00:00.000 Red
2016-06-25 06:00:00.000 Blue
2016-06-26 06:00:00.000 Blue
2016-06-27 06:00:00.000 Blue
2016-06-28 06:00:00.000 Blue
2016-06-29 06:00:00.000 Red
2016-06-30 06:00:00.000 Red
UDF:
CREATE FUNCTION [dbo].[udf-Create-Range-Date] (@DateFrom datetime,@DateTo datetime,@DatePart varchar(10),@Incr int)
Returns
@ReturnVal Table (RetVal datetime)
As
Begin
With DateTable As (
Select DateFrom = @DateFrom
Union All
Select Case @DatePart
When 'YY' then DateAdd(YY, @Incr, df.dateFrom)
When 'QQ' then DateAdd(QQ, @Incr, df.dateFrom)
When 'MM' then DateAdd(MM, @Incr, df.dateFrom)
When 'WK' then DateAdd(WK, @Incr, df.dateFrom)
When 'DD' then DateAdd(DD, @Incr, df.dateFrom)
When 'HH' then DateAdd(HH, @Incr, df.dateFrom)
When 'MI' then DateAdd(MI, @Incr, df.dateFrom)
When 'SS' then DateAdd(SS, @Incr, df.dateFrom)
End
From DateTable DF
Where DF.DateFrom < @DateTo
)
Insert into @ReturnVal(RetVal) Select DateFrom From DateTable option (maxrecursion 32767)
Return
End
-- Syntax Select * from [dbo].[udf-Create-Range-Date]('2016-10-01','2020-10-01','YY',1)
-- Syntax Select * from [dbo].[udf-Create-Range-Date]('2016-10-01','2020-10-01','DD',1)
-- Syntax Select * from [dbo].[udf-Create-Range-Date]('2016-10-01','2016-10-31','MI',15)
-- Syntax Select * from [dbo].[udf-Create-Range-Date]('2016-10-01','2016-10-02','SS',1)