Click here to Skip to main content
16,016,882 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
I have two problems to solve. One is to change first day of the week to Tuesday and the other is to change month end to 25th and start date to 26th from February to November.
January should start from 1st to 25th whiles December should start from 26th of November to 31st December.

What I have tried:

I have been able to figure out the first part. Thus changing the first date of the week to Tuesday.

set datefirst 2;
Posted
Updated 4-Mar-20 0:41am

I'm not sure i understand you well, but...

You can use CTE[^] for such of requrement:
[EDIT comment="After second read"]
SQL
DECLARE @initstartdate DATE = '2020-01-01';
DECLARE @initenddate DATE = '2020-12-31';

;WITH CTE AS
(
	--initial query
	SELECT @initstartdate startdate, DATEADD(DD, 24, @initstartdate) enddate
	UNION ALL
	--recursive part
	SELECT DATEADD(DD, 1, enddate) startdate, CASE WHEN MONTH(DATEADD(MM, 1, enddate)) = 12 THEN @initenddate ELSE DATEADD(MM, 1, enddate) END
	FROM CTE 
	WHERE MONTH(enddate) < 12
)
SELECT *
FROM CTE


Result:
2020-01-01	2020-01-25
2020-01-26	2020-02-25
2020-02-26	2020-03-25
2020-03-26	2020-04-25
2020-04-26	2020-05-25
2020-05-26	2020-06-25
2020-06-26	2020-07-25
2020-07-26	2020-08-25
2020-08-26	2020-09-25
2020-09-26	2020-10-25
2020-10-26	2020-11-25
2020-11-26	2020-12-31

[/END EDIT]
 
Share this answer
 
v2
Comments
wizy@2020 4-Mar-20 3:44am    
Good Maciej.
What I want to really achieve is to have the following results
e.g
RecDate	        MonthNo
2020-01-01	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.
Maciej Los 4-Mar-20 6:44am    
See solution #4.
Mine is alittle more code heavy, but any which way you would have to do this without a set pattern for each month.

SQL
declare @dateTable table ( id int identity(1,1), sDate date, eDate date)

declare @min int = 1 , @max int = 12
declare @sdate date = '2020-01-01'
declare @edate date = '2020-01-25'
declare @eDateTm datetime
declare @sDateTm datetime

while @min <= @max
begin 
if @min = 100
	begin
		break;
	end
	
	if @min > 1
	begin
		if month(@sdate) < 11
		begin
		set @eDateTm = dateAdd(MM, 1 , @sdate)
		set @eDateTm = dateAdd(dd, -1 , @eDateTm)
		set @edate = cast(@eDateTm as date)
		
		insert into @dateTable 
		select @sdate , @edate

		set @sDateTm = dateAdd(dd, +1 , @eDateTm)
		set @sdate = cast(@sDateTm as date)
		end
		else
		begin
			set @edate = '2020-12-31'
			insert into @dateTable 
			select @sdate , @edate
		end
	end
	else
	begin
		insert into @dateTable 
		select @sdate , @edate
		set @sDateTm = dateAdd(dd, +1 , @eDate)
		set @sdate = cast(@sDateTm as date)

	end
	set @min = @min + 1
	--select @min

end

select * from @dateTable
 
Share this answer
 
v2
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:
SQL
--initial range
DECLARE @initstartdate DATE = CAST('2019-01-01' AS DATE); --define initial start date
DECLARE @initenddate DATE = CAST('2020-12-31' AS DATE); --define initial end date
--declare and fill-in reference table to store fiscal year details
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)

--get all dates between initial start date and end date
;WITH alldates AS
(
	SELECT @initstartdate RecDate
	UNION ALL
	SELECT DATEADD(DD, 1, RecDate) RecDate 
	FROM alldates
	WHERE DATEADD(DD, 1, RecDate)<=@initenddate 
),
--get fiscal year details for years between initial start date and end date
	dateranges AS
	(
		--initial query
		SELECT DATEFROMPARTS(YEAR(@initstartdate), refmonthfrom, refdayfrom ) startdate, DATEFROMPARTS(YEAR(@initstartdate), refmonthto, refdayto) enddate, fiscalmonth
		FROM @reftable
		UNION ALL
		----recursive part
		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 
	)
-- mix all together ;)
	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.
 
Share this answer
 
v3

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900