first, you need to make calendar full year or full month, so I would use cte recursion to make it.
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
there is 7 days in a week, whatever started with any week, then we will saw this a Gaps and Islands problem, because the week number will repeat from 1
to 7
.
So I would use CASE WHEN
with DateNameto make your customer week date number, which number starts on
Friday` or depending on your logic.
;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
[Results]:
| 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 |
then we can try to use rn - grp
to get the group, which is continuous.
[Results]:
| 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 |
final, we just get all count(*) = 7
group in month or year number, which mean complete weeks.
Query 1:
full month
;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 |
full year
;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
Note
if your cte recursion date more than 100 you will get the error
The statement terminated. The maximum recursion 100 has been exhausted before statement completion.
you can set
option (maxrecursion 0)
The Case When
number 0
and 1
mean your weekoff day