根据定制周末计算周数

问题描述 投票:2回答:2

不同的组织可能会有不同的休假。所以,在这种情况下,需要定制休息周。为此,我尝试了下面的Sql查询

DECLARE @dayName VARCHAR(9);
SET @dayName = DATEName(DW, GETDATE());

IF(@dayName = 'Friday' OR @dayName = 'Saturday') 
    PRINT 'Weekend';
ELSE
    PRINT 'NOT Weekend';

从上面的查询我可以得到我特定的周末。

例如:

如果星期五或任何其他日子被提及为周末,那么从周五到周四对应一周,我需要找到一个月内有多少个完整周?还是一年?

我希望在定制的weekOff的基础上获得周数。

c# sql sql-server date weekday
2个回答
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,因为周数将从1to 7重复。

所以我会使用CASE WHEN与DateNameto make your customer week date number, which number starts onFriday`或根据你的逻辑。

 ;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)

sqlfiddle

注意

如果您的cte递归日期超过100,您将收到错误

声明终止。在语句完成之前,最大递归100已用尽。

你可以设置

option (maxrecursion 0)

qazxsw poi number qazxsw poi和qazxsw poi意味着你的休息日


2
投票

替代解决方案,

Case When
© www.soinside.com 2019 - 2024. All rights reserved.