不同的组织可能会有不同的一周休息时间。 因此,在这种情况下,需要自定义休假。为此,我尝试了 SQL查询写在下面
DECLARE @dayName VARCHAR(9);
SET @dayName = DATEName(DW, GETDATE());
IF(@dayName = 'Friday' OR @dayName = 'Saturday')
PRINT 'Weekend';
ELSE
PRINT 'NOT Weekend';
从上面的查询中,我可以得到特定的休假。
例如:
如果提到星期五或其他任何一天作为周末,那么从星期五到星期四对应一个星期,我需要找出一个月中有多少完整的星期?还是一年?
我想根据自定义的weekOff获取星期数。
答案 0 :(得分:2)
首先,您需要将日历设置为整年或整月,因此我将使用 cte递归进行设置。
SELECT DATEADD(month, DATEDIFF(month, 0, getdate()), 0) AS StartOfMonth,
DATEADD(mm,1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0)) - 1 AS EndOfMonth
UNION ALL
SELECT StartOfMonth +1 , EndOfMonth
FROM CTE
WHERE StartOfMonth < EndOfMonth
一周中有7天,无论从任何一周开始,都将看到Gaps and Islands problem,因为周数将从1
重复到7
。
因此,我将CASE WHEN
与DateName to make your customer week date number, which number starts on
Friday`配合使用,或根据您的逻辑使用。
;WITH CTE AS (
SELECT DATEADD(month, DATEDIFF(month, 0, getdate()), 0) AS StartOfMonth,
DATEADD(mm,1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0)) - 1 AS EndOfMonth
UNION ALL
SELECT StartOfMonth +1 , EndOfMonth
FROM CTE
WHERE StartOfMonth < EndOfMonth
)
SELECT *,
CASE DateName(DW, StartOfMonth)
WHEN 'Friday' THEN 0
WHEN 'Saturday' THEN 1
WHEN 'Sunday' THEN 2
WHEN 'Monday' THEN 3
WHEN 'Tuesday' THEN 4
WHEN 'Wednesday' THEN 5
WHEN 'Thursday' THEN 6
WHEN 'Tuesday' THEN 7
END grp,
ROW_NUMBER() OVER(ORDER BY StartOfMonth) rn
FROM CTE
[结果] :
| StartOfMonth | EndOfMonth | grp | rn |
|----------------------|----------------------|-----|----|
| 2018-09-01T00:00:00Z | 2018-09-30T00:00:00Z | 1 | 1 |
| 2018-09-02T00:00:00Z | 2018-09-30T00:00:00Z | 2 | 2 |
| 2018-09-03T00:00:00Z | 2018-09-30T00:00:00Z | 3 | 3 |
| 2018-09-04T00:00:00Z | 2018-09-30T00:00:00Z | 4 | 4 |
| 2018-09-05T00:00:00Z | 2018-09-30T00:00:00Z | 5 | 5 |
| 2018-09-06T00:00:00Z | 2018-09-30T00:00:00Z | 6 | 6 |
| 2018-09-07T00:00:00Z | 2018-09-30T00:00:00Z | 0 | 7 |
| 2018-09-08T00:00:00Z | 2018-09-30T00:00:00Z | 1 | 8 |
| 2018-09-09T00:00:00Z | 2018-09-30T00:00:00Z | 2 | 9 |
| 2018-09-10T00:00:00Z | 2018-09-30T00:00:00Z | 3 | 10 |
| 2018-09-11T00:00:00Z | 2018-09-30T00:00:00Z | 4 | 11 |
| 2018-09-12T00:00:00Z | 2018-09-30T00:00:00Z | 5 | 12 |
| 2018-09-13T00:00:00Z | 2018-09-30T00:00:00Z | 6 | 13 |
| 2018-09-14T00:00:00Z | 2018-09-30T00:00:00Z | 0 | 14 |
| 2018-09-15T00:00:00Z | 2018-09-30T00:00:00Z | 1 | 15 |
| 2018-09-16T00:00:00Z | 2018-09-30T00:00:00Z | 2 | 16 |
| 2018-09-17T00:00:00Z | 2018-09-30T00:00:00Z | 3 | 17 |
| 2018-09-18T00:00:00Z | 2018-09-30T00:00:00Z | 4 | 18 |
| 2018-09-19T00:00:00Z | 2018-09-30T00:00:00Z | 5 | 19 |
| 2018-09-20T00:00:00Z | 2018-09-30T00:00:00Z | 6 | 20 |
| 2018-09-21T00:00:00Z | 2018-09-30T00:00:00Z | 0 | 21 |
| 2018-09-22T00:00:00Z | 2018-09-30T00:00:00Z | 1 | 22 |
| 2018-09-23T00:00:00Z | 2018-09-30T00:00:00Z | 2 | 23 |
| 2018-09-24T00:00:00Z | 2018-09-30T00:00:00Z | 3 | 24 |
| 2018-09-25T00:00:00Z | 2018-09-30T00:00:00Z | 4 | 25 |
| 2018-09-26T00:00:00Z | 2018-09-30T00:00:00Z | 5 | 26 |
| 2018-09-27T00:00:00Z | 2018-09-30T00:00:00Z | 6 | 27 |
| 2018-09-28T00:00:00Z | 2018-09-30T00:00:00Z | 0 | 28 |
| 2018-09-29T00:00:00Z | 2018-09-30T00:00:00Z | 1 | 29 |
| 2018-09-30T00:00:00Z | 2018-09-30T00:00:00Z | 2 | 30 |
然后我们可以尝试使用rn - grp
来获取连续的组。
[结果] :
| StartOfMonth | EndOfMonth | grp |
|----------------------|----------------------|-----|
| 2018-09-01T00:00:00Z | 2018-09-30T00:00:00Z | 0 |
| 2018-09-02T00:00:00Z | 2018-09-30T00:00:00Z | 0 |
| 2018-09-03T00:00:00Z | 2018-09-30T00:00:00Z | 0 |
| 2018-09-04T00:00:00Z | 2018-09-30T00:00:00Z | 0 |
| 2018-09-05T00:00:00Z | 2018-09-30T00:00:00Z | 0 |
| 2018-09-06T00:00:00Z | 2018-09-30T00:00:00Z | 0 |
| 2018-09-07T00:00:00Z | 2018-09-30T00:00:00Z | 7 |
| 2018-09-08T00:00:00Z | 2018-09-30T00:00:00Z | 7 |
| 2018-09-09T00:00:00Z | 2018-09-30T00:00:00Z | 7 |
| 2018-09-10T00:00:00Z | 2018-09-30T00:00:00Z | 7 |
| 2018-09-11T00:00:00Z | 2018-09-30T00:00:00Z | 7 |
| 2018-09-12T00:00:00Z | 2018-09-30T00:00:00Z | 7 |
| 2018-09-13T00:00:00Z | 2018-09-30T00:00:00Z | 7 |
| 2018-09-14T00:00:00Z | 2018-09-30T00:00:00Z | 14 |
| 2018-09-15T00:00:00Z | 2018-09-30T00:00:00Z | 14 |
| 2018-09-16T00:00:00Z | 2018-09-30T00:00:00Z | 14 |
| 2018-09-17T00:00:00Z | 2018-09-30T00:00:00Z | 14 |
| 2018-09-18T00:00:00Z | 2018-09-30T00:00:00Z | 14 |
| 2018-09-19T00:00:00Z | 2018-09-30T00:00:00Z | 14 |
| 2018-09-20T00:00:00Z | 2018-09-30T00:00:00Z | 14 |
| 2018-09-21T00:00:00Z | 2018-09-30T00:00:00Z | 21 |
| 2018-09-22T00:00:00Z | 2018-09-30T00:00:00Z | 21 |
| 2018-09-23T00:00:00Z | 2018-09-30T00:00:00Z | 21 |
| 2018-09-24T00:00:00Z | 2018-09-30T00:00:00Z | 21 |
| 2018-09-25T00:00:00Z | 2018-09-30T00:00:00Z | 21 |
| 2018-09-26T00:00:00Z | 2018-09-30T00:00:00Z | 21 |
| 2018-09-27T00:00:00Z | 2018-09-30T00:00:00Z | 21 |
| 2018-09-28T00:00:00Z | 2018-09-30T00:00:00Z | 28 |
| 2018-09-29T00:00:00Z | 2018-09-30T00:00:00Z | 28 |
| 2018-09-30T00:00:00Z | 2018-09-30T00:00:00Z | 28 |
最后,我们只得到月份或年份中的所有count(*) = 7
组,这意味着整周。
查询1 :
整月
;WITH CTE AS (
SELECT DATEADD(month, DATEDIFF(month, 0, getdate()), 0) AS StartOfMonth,
DATEADD(mm,1,DATEADD(mm, DATEDIFF(m,0,GETDATE()),0)) - 1 AS EndOfMonth
UNION ALL
SELECT StartOfMonth +1 , EndOfMonth
FROM CTE
WHERE StartOfMonth < EndOfMonth
)
SELECT COUNT(*) fullweekAmount from (
SELECT
MIN(StartOfMonth) startdt,
MAX(StartOfMonth) enddt
FROM (
SELECT *,
ROW_NUMBER() OVER(ORDER BY StartOfMonth) -
CASE DateName(DW, StartOfMonth)
WHEN 'Friday' THEN 0
WHEN 'Saturday' THEN 1
WHEN 'Sunday' THEN 2
WHEN 'Monday' THEN 3
WHEN 'Tuesday' THEN 4
WHEN 'Wednesday' THEN 5
WHEN 'Thursday' THEN 6
WHEN 'Tuesday' THEN 7
END grp
FROM CTE
) t1
GROUP BY grp
having count(*) = 7
) t1
Results :
| fullweekAmount |
|----------------|
| 3 |
全年
;WITH CTE AS (
SELECT DATEADD(yy, DATEDIFF(yy, 0, GETDATE()), 0) AS StartOfMonth,
DATEADD(yy, DATEDIFF(yy, 0, GETDATE()) + 1, -1) - 1 AS EndOfMonth
UNION ALL
SELECT StartOfMonth +1 , EndOfMonth
FROM CTE
WHERE StartOfMonth < EndOfMonth
)
SELECT COUNT(*) fullweekAmount from (
SELECT
MIN(StartOfMonth) startdt,
MAX(StartOfMonth) enddt
FROM (
SELECT *,
ROW_NUMBER() OVER(ORDER BY StartOfMonth) -
CASE DateName(DW, StartOfMonth)
WHEN 'Friday' THEN 0
WHEN 'Saturday' THEN 1
WHEN 'Sunday' THEN 2
WHEN 'Monday' THEN 3
WHEN 'Tuesday' THEN 4
WHEN 'Wednesday' THEN 5
WHEN 'Thursday' THEN 6
WHEN 'Tuesday' THEN 7
END grp
FROM CTE
) t1
GROUP BY grp
having count(*) = 7
) t1
option (maxrecursion 0)
注意
如果 cte递归日期超过100,则会收到错误消息
该语句终止。语句完成之前,最大递归100已用尽。
您可以设置
option (maxrecursion 0)
Case When
数字0
和1
表示您的休假日
答案 1 :(得分:2)
替代解决方案
DECLARE @StartDate DATE='20200722'--any valid date as your requirement needs(it is inclusive of the specified date)
DECLARE @MonthorYear CHAR='Y'--Valid inputs: 'M'->for month and 'Y'-> for year
DECLARE @WeekdayBeginning nVarchar(15)='Sunday'
----Valid inputs run the following query, in my case it is english, for you it may differ based on your language
--SELECT DATENAME(dw, DATEADD(d,-1,'20180903')) Union all
--SELECT DATENAME(dw, DATEADD(d,0,'20180903')) Union all
--SELECT DATENAME(dw, DATEADD(d,1,'20180903')) Union all
--SELECT DATENAME(dw, DATEADD(d,2,'20180903')) Union all
--SELECT DATENAME(dw, DATEADD(d,3,'20180903')) Union all
--SELECT DATENAME(dw, DATEADD(d,4,'20180903')) Union all
--SELECT DATENAME(dw, DATEADD(d,5,'20180903'))
DECLARE @week TABLE
(ID int identity(0,1),DoW nVarchar(15),isWeekstart bit default 0)
INSERT INTO @week (DoW)
SELECT DATENAME(dw, DATEADD(d,-1,'20180903')) Union all
SELECT DATENAME(dw, DATEADD(d,0,'20180903')) Union all
SELECT DATENAME(dw, DATEADD(d,1,'20180903')) Union all
SELECT DATENAME(dw, DATEADD(d,2,'20180903')) Union all
SELECT DATENAME(dw, DATEADD(d,3,'20180903')) Union all
SELECT DATENAME(dw, DATEADD(d,4,'20180903')) Union all
SELECT DATENAME(dw, DATEADD(d,5,'20180903'))
-- input validations
if not exists (SELECT 1 FROM @week where DoW=@WeekdayBeginning)
BEGIN
PRINT 'Invalid @WeekdayBeginning input'
RETURN
END
if (@MonthorYear NOT IN ('M','Y'))
BEGIN
PRINT 'Invalid @MonthorYear input'
RETURN
END
--Start of find logic
DECLARE @EndDate date
DECLARE @DaysMissed tinyint,@TempDays smallint,@Weeks tinyint
SELECT @EndDate=
case @MonthorYear WHEN 'M' THEN EOMONTH(@StartDate)
ELSE DATEFROMPARTS(YEAR(@StartDate),12,31) END
UPDATE @week set isWeekstart=1 where Dow=@WeekdayBeginning
SELECT @TempDays=DATEDIFF(d,@StartDate,@EndDate)+1
if not exists(SELECT 1 FROM @week WHERE DATENAME(dw,@StartDate)=DoW and isWeekstart=1)
BEGIN
DECLARE @tempID tinyint,@WeekstartID tinyint
SELECT @tempID=ID from @week WHERE DATENAME(dw,@StartDate)=DoW
SELECT @WeekstartID=ID from @week WHERE isWeekstart=1
WHILE(@WeekstartID<>@tempID)
BEGIN
SET @TempDays=@TempDays-1
SET @tempID=@tempID+1
if(@tempID>6)
BEGIN
SET @tempID=0
END
END
END
SET @Weeks=@TempDays/7
SELECT @Weeks as 'CompleteWeeks'