wizy@2020 wrote:
Good Maciej.
What I want to really achieve is to have the following results
e.g
RecDate MonthNo
2020-01-01 1
2020-01-02 1
...
2020-01-25 1
2020-01-26 2
...
2020-02-25 2
2020-02-26 3
...
up to
2020-12-31 12
I have a table with over 20000 records and want to at any point get the correct month number. This should be able to work with any year.
This query should produce a set due to the OP's needs:
DECLARE @initstartdate DATE = CAST('2019-01-01' AS DATE);
DECLARE @initenddate DATE = CAST('2020-12-31' AS DATE);
DECLARE @reftable TABLE(refdayfrom INT, refmonthfrom INT, refdayto INT, refmonthto INT, fiscalmonth INT)
INSERT INTO @reftable(refdayfrom, refmonthfrom, refdayto, refmonthto, fiscalmonth)
VALUES(1, 1, 25, 1, 1),
(26, 1, 25, 2, 2),
(26, 2, 25, 3, 3),
(26, 3, 25, 4, 4),
(26, 4, 25, 5, 5),
(26, 5, 25, 6, 6),
(26, 6, 25, 7, 7),
(26, 7, 25, 8, 8),
(26, 8, 25, 9, 9),
(26, 9, 25, 10, 10),
(26, 10, 25, 11, 11),
(26, 11, 31, 12, 12)
;WITH alldates AS
(
SELECT @initstartdate RecDate
UNION ALL
SELECT DATEADD(DD, 1, RecDate) RecDate
FROM alldates
WHERE DATEADD(DD, 1, RecDate)<=@initenddate
),
dateranges AS
(
SELECT DATEFROMPARTS(YEAR(@initstartdate), refmonthfrom, refdayfrom ) startdate, DATEFROMPARTS(YEAR(@initstartdate), refmonthto, refdayto) enddate, fiscalmonth
FROM @reftable
UNION ALL
SELECT DATEFROMPARTS(YEAR(DATEADD(YY, 1, startdate)), MONTH(startdate), DAY(startdate)) startdate,
DATEFROMPARTS(YEAR(DATEADD(YY, 1, enddate)), MONTH(enddate), DAY(enddate)) enddate, fiscalmonth
FROM dateranges
WHERE DATEADD(YY, 1, enddate)<= @initenddate
)
SELECT ad.RecDate, dr.fiscalmonth MonthNo
FROM alldates ad INNER JOIN dateranges dr ON ad.RecDate BETWEEN dr.startdate AND dr.enddate
ORDER BY RecDate
OPTION (MAXRECURSION 0);
Above query produces (731 records in 0.001 seconds):
RecDate MonthNo
2019-01-01 1
up to
2020-12-31 12
Note: you can create reference table as a physical table (not a variable /type of table/). Then you'll be able to use it in query without creating and filling-in a variable.