I want to get a custom Fort Night period based on a given start date.
I have a table that looks like this:
IF OBJECT_ID('tempdb..#tbl1') IS NOT NULL DROP TABLE #tbl1
SET DATEFIRST 1
DECLARE #StartDateTime DATETIME
DECLARE #EndDateTime DATETIME
SET #StartDateTime = '2016-09-03'
SET #EndDateTime = '2017-01-28';
WITH DateRange(DateData) AS
(
SELECT #StartDateTime as Date
UNION ALL
SELECT DATEADD(d,1,DateData)
FROM DateRange
WHERE DateData < #EndDateTime
)
SELECT ROW_NUMBER() OVER(ORDER BY DateData ASC) As ROWNum,DateData AS Date1
into #tbl1
FROM DateRange
OPTION (MAXRECURSION 0)
GO
SELECT top 10 * FROM #tbl1
Date1
2016-09-09 00:00:00.000
2016-09-10 00:00:00.000
2016-09-11 00:00:00.000
2016-09-12 00:00:00.000
2016-09-13 00:00:00.000
2016-09-14 00:00:00.000
2016-09-15 00:00:00.000
2016-09-16 00:00:00.000
2016-09-17 00:00:00.000
2016-09-18 00:00:00.000
2016-09-19 00:00:00.000
2016-09-20 00:00:00.000
2016-09-21 00:00:00.000
2016-09-22 00:00:00.000
I want to say the the first date of my bi-weekly period is 2016-09-09 and it ends 2016-09-22. How do I get bi-weekly end date for each of those dates.
So I want it to look like
Date1 FortNightEndDate
2016-09-09 00:00:00.000 2016-09-22 00:00:00.000
2016-09-10 00:00:00.000 2016-09-22 00:00:00.000
2016-09-11 00:00:00.000 2016-09-22 00:00:00.000
2016-09-12 00:00:00.000 2016-09-22 00:00:00.000
2016-09-13 00:00:00.000 2016-09-22 00:00:00.000
2016-09-14 00:00:00.000 2016-09-22 00:00:00.000
2016-09-15 00:00:00.000 2016-09-22 00:00:00.000
2016-09-16 00:00:00.000 2016-09-22 00:00:00.000
2016-09-17 00:00:00.000 2016-09-22 00:00:00.000
2016-09-18 00:00:00.000 2016-09-22 00:00:00.000
2016-09-19 00:00:00.000 2016-09-22 00:00:00.000
2016-09-20 00:00:00.000 2016-09-22 00:00:00.000
2016-09-21 00:00:00.000 2016-09-22 00:00:00.000
2016-09-22 00:00:00.000 2016-09-22 00:00:00.000
I'm using SQL Server 2005.
ANSWER:
I was able to solve it using the following code. Essentially I just created 3 tables:
StartDates
EndDates
InbetweenDates
The Start/EndDates tables had just the start and End of my 2 week period and an ID (Row Number)
The InbetweenDates table had all the dates between the 2 dates and also had a ID column but instead of going up 1 every row, it went up 1 every 14 rows.
Then I just joined the 3 tables. Essentially, the Start/EndDates tables were lookup tables.
I got the RowNumber on every 14 days code from here.
-- BEtween Dates
IF OBJECT_ID('tempdb..#BetweenDates') IS NOT NULL DROP TABLE #BetweenDates
DECLARE #StartDateTime DATETIME
DECLARE #EndDateTime DATETIME
SET #StartDateTime = '2016-09-09'
SET #EndDateTime = '2017-04-30';
WITH DateRange(DateData) AS
(
SELECT #StartDateTime as Date
UNION ALL
SELECT DATEADD(d,1,DateData)
FROM DateRange
WHERE DateData < #EndDateTime
)
SELECT
DateData
into #BetweenDates
FROM DateRange
OPTION (MAXRECURSION 0)
GO
select
(case when convert(int, (ROW_NUMBER() OVER (Order by (select 0)) % 14))=0 then 0 else 1 end)
+ convert(int, (ROW_NUMBER() OVER (Order by (select 0)) / 14)) as ID
,DateData
INTO #BetweenDates_ID
from #BetweenDates
-- Start Dates
IF OBJECT_ID('tempdb..#StartDates') IS NOT NULL DROP TABLE #StartDates
DECLARE #StartDateTime DATETIME
DECLARE #EndDateTime DATETIME
SET #StartDateTime = '2016-09-09'
SET #EndDateTime = '2017-04-30';
WITH DateRange(DateData) AS
(
SELECT #StartDateTime as Date
UNION ALL
SELECT DATEADD(d,14,DateData)
FROM DateRange
WHERE DateData < #EndDateTime
)
SELECT ROW_NUMBER() OVER(ORDER BY DateData ASC) As ID,DateData
into #StartDates
FROM DateRange
OPTION (MAXRECURSION 0)
GO
-- End Dates
IF OBJECT_ID('tempdb..#EndDates') IS NOT NULL DROP TABLE #EndDates
DECLARE #StartDateTime DATETIME
DECLARE #EndDateTime DATETIME
SET #StartDateTime = '2016-09-22'
SET #EndDateTime = '2017-04-30';
WITH DateRange(DateData) AS
(
SELECT #StartDateTime as Date
UNION ALL
SELECT DATEADD(d,14,DateData)
FROM DateRange
WHERE DateData < #EndDateTime
)
SELECT ROW_NUMBER() OVER(ORDER BY DateData ASC) As ID,DateData
into #EndDates
FROM DateRange
OPTION (MAXRECURSION 0)
GO
--SELECT * FROM #StartDates
--SELECT * FROM #EndDates
--SELECT * FROM #BetweenDates_ID
SELECT
st.DateData AS StartDate
,ed.DateData AS EndDate
,bd.DateData AS BetweenDate
FROM
#StartDates st
JOIN
#EndDates ed
ON st.ID = ed.ID
LEFT JOIN
#BetweenDates_ID bd
ON st.ID = bd.ID
Try this:
SELECT Date1,
DATEADD(DD, -1, DATEADD(WW,2,Date1)) AS FortNightEndDate
FROM #tbl1
Related
Let's give a datetime 2019-04-22 00:00:00.000 (midnight of 22 April 2019)
Now I have a table of records that contains a StartDate and EndDate
ID StartDate EndDate
--------------------------------------------------------------------------
1 2019-04-15 00:00:00.000 2019-04-18 00:00:00.000
2 2019-04-16 00:00:00.000 2019-04-28 00:00:00.000
3 2019-04-23 00:00:00.000 2019-04-25 00:00:00.000
How can I split record with ID = 2 so that I get two records:
record one start date: 2019-04-16 00:00:00.000 and end date: 2019-04-21 23:59:59.000
record two start date: 2019-04-22 00:00:00.000 and end date: 2019-04-28 00:00:00.000
Basically if a range has the start date before 2019-04-22 00:00:00.000 and end date after 2019-04-22 00:00:00.000 then split that record into two records where the end date will be midnight before 2019-04-22 00:00:00.000 for the first record and start date will become 2019-04-22 00:00:00.000 for the second record.
I'd do a UNION ALL, where the first SELECT returns all rows starting before given datetime, and the second SELECT returns all rows ending after that datetime. Something like:
select id, startdate, case when EndDate < '2019-04-22 00:00:00.000' then EndDate
else '2019-04-22 00:00:00.000' end EndDate
from tablename
where startdate < '2019-04-22 00:00:00.000'
UNION ALL
select id, case when startdate > '2019-04-22 00:00:00.000' then startdate
else '2019-04-22 00:00:00.000' end,
EndDate
from tablename
where EndDate > '2019-04-22 00:00:00.000'
The case expressions are there to adjust start or end time for the overlapping rows, those who are splitted into two separate rows.
You can use the following solution:
DECLARE #splitDate DATE = '2019-04-22 00:00:00.000';
SELECT ID, StartDate, (select min(i) from (values (test.EndDate), (#splitDate)) AS T(i)) AS EndDate
FROM table_name WHERE StartDate < #splitDate
UNION ALL
SELECT ID, (select max(i) from (values (test.StartDate), (#splitDate)) AS T(i)) AS StartDate, EndDate
FROM table_name WHERE EndDate > #splitDate
demo on dbfiddle.uk
I have a table like
ID StartDate EndDate
AAA 2017-03-17 00:00:00.000 2017-03-19 00:00:00.000
BB 2017-06-20 00:00:00.000 2017-06-25 00:00:00.000
CC 2017-05-13 00:00:00.000 2017-05-17 00:00:00.000
DD 2017-06-20 00:00:00.000 2017-05-27 00:00:00.000
EE 2017-03-01 00:00:00.000 2017-03-05 00:00:00.000
FF 2017-08-07 00:00:00.000 2017-08-11 00:00:00.000
i need the missing dates in between these ranges and the output table should be like
ID Date
AAA 2017-03-17 00:00:00.000 -- Start date for AAA
AAA 2017-03-18 00:00:00.000
AAA 2017-03-19 00:00:00.000 -- End date for AAA
BB 2017-06-20 00:00:00.000 -- start date for BB
BB 2017-06-21 00:00:00.000
BB 2017-06-22 00:00:00.000
BB 2017-06-23 00:00:00.000
BB 2017-06-24 00:00:00.000
BB 2017-06-25 00:00:00.000 -- End date for BB
You need to add loop to get dates between start and end dates , Example :
DECLARE #table table (ID Varchar(50), StartDate datetime,EndDate datetime)
insert into #table values ('AAA','2017-03-17 00:00:00.000',' 2017-03-19 00:00:00.000')
insert into #table values ('BB','2017-06-20 00:00:00.000 ',' 2017-06-25 00:00:00.000')
insert into #table values ('CC','2017-05-13 00:00:00.000 ',' 2017-05-17 00:00:00.000')
insert into #table values ('DD','2017-06-20 00:00:00.000 ',' 2017-05-27 00:00:00.000')
insert into #table values ('EE','2017-03-01 00:00:00.000 ',' 2017-03-05 00:00:00.000')
insert into #table values ('FF','2017-08-07 00:00:00.000 ',' 2017-08-11 00:00:00.000')
SELECT * FROM #table
SELECT id, StartDate FROM #table WHERE id='AAA'
union all
SELECT id, Dateadd(day,1,startdate) AS date FROM #table WHERE id='AAA' AND Dateadd(day,1,startdate)<EndDate
union all
SELECT id, EndDate FROM #table WHERE id='AAA'
union all
SELECT id, StartDate FROM #table WHERE id='BB'
union all
SELECT id, Dateadd(day,1,startdate) AS date FROM #table WHERE id='BB' AND Dateadd(day,1,startdate)<EndDate
union all
SELECT id, EndDate FROM #table WHERE id='BB'
union all
SELECT id, StartDate FROM #table WHERE id='CC'
union all
SELECT id, Dateadd(day,1,startdate) AS date FROM #table WHERE id='CC' AND Dateadd(day,1,startdate)<EndDate
union all
SELECT id, EndDate FROM #table WHERE id='CC'
union all
SELECT id, StartDate FROM #table WHERE id='DD'
union all
SELECT id, Dateadd(day,1,startdate) AS date FROM #table WHERE id='DD' AND Dateadd(day,1,startdate)<EndDate
union all
SELECT id, EndDate FROM #table WHERE id='DD'
union all
SELECT id, StartDate FROM #table WHERE id='EE'
union all
SELECT id, Dateadd(day,1,startdate) AS date FROM #table WHERE id='EE' AND Dateadd(day,1,startdate)<EndDate
union all
SELECT id, EndDate FROM #table WHERE id='EE'
union all
SELECT id, StartDate FROM #table WHERE id='FF'
union all
SELECT id, Dateadd(day,1,startdate) AS date FROM #table WHERE id='FF' AND Dateadd(day,1,startdate)<EndDate
union all
SELECT id, EndDate FROM #table WHERE id='FF'
Output:
id StartDate
AAA 2017-03-17 00:00:00.000
AAA 2017-03-18 00:00:00.000
AAA 2017-03-19 00:00:00.000
BB 2017-06-20 00:00:00.000
BB 2017-06-21 00:00:00.000
BB 2017-06-25 00:00:00.000
CC 2017-05-13 00:00:00.000
CC 2017-05-14 00:00:00.000
CC 2017-05-17 00:00:00.000
DD 2017-06-20 00:00:00.000
DD 2017-05-27 00:00:00.000
EE 2017-03-01 00:00:00.000
EE 2017-03-02 00:00:00.000
EE 2017-03-05 00:00:00.000
FF 2017-08-07 00:00:00.000
FF 2017-08-08 00:00:00.000
FF 2017-08-11 00:00:00.000
First, i created a calendar table based on your MIN and MAX date to get all the dates involved. Then i joined it to your table.
DECLARE #calendar AS TABLE ([Date] DATETIME)
DECLARE #maxDate AS DATETIME = (SELECT CASE WHEN MAX(StartDate) > MAX(EndDate)
THEN MAX(StartDate)
ELSE MAX(EndDate)
END FROM #YourTable)
DECLARE #minDate AS DATETIME = (SELECT CASE WHEN MIN(StartDate) < MIN(EndDate)
THEN MIN(StartDate)
ELSE MIN(EndDate)
END FROM #YourTable)
WHILE (#minDate < #maxDate)
BEGIN
INSERT INTO #calendar
VALUES (#minDate)
SET #minDate = DATEADD(DAY, 1, #minDate)
END
SELECT [Id], a.[Date]
FROM (Select [Date] FROM #calendar) a
LEFT JOIN #YourTable ON [Date] BETWEEN [StartDate] AND [EndDate]
WHERE [Id] IS NOT NULL
CREATE TABLE t
(
ID NVARCHAR(5) NOT NULL ,
StartDate DATETIME NOT NULL ,
EndDate DATETIME NOT NULL
);
GO
INSERT INTO dbo.t
( ID, StartDate, EndDate )
VALUES ( N'AAA', '2017-03-17 00:00:00.000', '2017-03-19 00:00:00.000' ),
( N'BB', '2017-06-20 00:00:00.000', '2017-06-25 00:00:00.000' ),
( N'CC', '2017-05-13 00:00:00.000', '2017-05-17 00:00:00.000' ),
( N'DD', '2017-06-20 00:00:00.000', '2017-05-27 00:00:00.000' ),
( N'EE', '2017-03-01 00:00:00.000', '2017-03-05 00:00:00.000' ),
( N'FF', '2017-08-07 00:00:00.000', '2017-08-11 00:00:00.000' );
WITH cte
AS ( SELECT ID ,
StartDate
FROM dbo.t
UNION ALL
SELECT cte.ID ,
DATEADD(DAY, 1, cte.StartDate)
FROM cte
INNER JOIN dbo.t ON t.ID = cte.ID
WHERE cte.StartDate < EndDate
)
SELECT cte.ID ,
cte.StartDate
FROM cte
ORDER BY cte.ID ,
cte.StartDate;
Result:
ID StartDate
----- -----------------------
AAA 2017-03-17 00:00:00.000
AAA 2017-03-18 00:00:00.000
AAA 2017-03-19 00:00:00.000
BB 2017-06-20 00:00:00.000
BB 2017-06-21 00:00:00.000
BB 2017-06-22 00:00:00.000
BB 2017-06-23 00:00:00.000
BB 2017-06-24 00:00:00.000
BB 2017-06-25 00:00:00.000
CC 2017-05-13 00:00:00.000
CC 2017-05-14 00:00:00.000
CC 2017-05-15 00:00:00.000
CC 2017-05-16 00:00:00.000
CC 2017-05-17 00:00:00.000
DD 2017-06-20 00:00:00.000
EE 2017-03-01 00:00:00.000
EE 2017-03-02 00:00:00.000
EE 2017-03-03 00:00:00.000
EE 2017-03-04 00:00:00.000
EE 2017-03-05 00:00:00.000
FF 2017-08-07 00:00:00.000
FF 2017-08-08 00:00:00.000
FF 2017-08-09 00:00:00.000
FF 2017-08-10 00:00:00.000
FF 2017-08-11 00:00:00.000
I have a table with two columns
start_date 03/09/2016
end_date 03/15/2016
Now I need all the week start and end dates between these two dates
week_start_date week_end_date
03/07/2016 03/11/2016
03/14/2016 03/18/2016
How can I achieve this using sql query. No procedures or t-sql please.
first you have to find all dates between #start_date and #end_date :
declare #start_date datetime
declare #end_date datetime
set #start_date='03/09/2016'
set #end_date='03/15/2016'
;
WITH dates AS (
SELECT #start_date AS dt
UNION ALL
SELECT DATEADD(dd, 1, dt)
FROM dates s
WHERE DATEADD(dd, 1, dt) <= #end_date)
result:
2016-03-09 00:00:00.000
2016-03-10 00:00:00.000
2016-03-11 00:00:00.000
2016-03-12 00:00:00.000
2016-03-13 00:00:00.000
2016-03-14 00:00:00.000
2016-03-15 00:00:00.000
second you need to find out weekday ,'2' is Monday week_start_date
'6' is friday week_end_date
select DATEPART(dw,'03/11/2016') -- friday =6
select DATEPART(dw,'03/14/2016') --- monday =2
here is the final query:
declare #start_date datetime
declare #end_date datetime
set #start_date='03/01/2016'
set #end_date='03/31/2016'
;
WITH sample AS (
SELECT #start_date AS dt
UNION ALL
SELECT DATEADD(dd, 1, dt)
FROM sample s
WHERE DATEADD(dd, 1, dt) <= #end_date)
, dayofWeekTemp as(
SELECT Cast(DATEPART(dw,s.dt) as int) dayOfWeekValue , s.dt dateValue
FROM sample s)
select Case when dayOfWeekValue =6 then 'End of week' when dayOfWeekValue=2 then 'Start of week' End,dateValue from dayofWeekTemp
where dayOfWeekValue=2 Or dayOfWeekValue=6
Results
End of week 2016-03-04 00:00:00.000
Start of week 2016-03-07 00:00:00.000
End of week 2016-03-11 00:00:00.000
Start of week 2016-03-14 00:00:00.000
End of week 2016-03-18 00:00:00.000
Start of week 2016-03-21 00:00:00.000
End of week 2016-03-25 00:00:00.000
Start of week 2016-03-28 00:00:00.000
I m working on a very weird problem with SQL where I have to compare previous rows
Number start_date end_date
----- ------- ------------
1 2011-06-07 00:00:00.000 2011-07-10 00:00:00.000
2 2011-10-11 00:00:00.000 2011-10-11 00:00:00.000
3 2011-10-26 00:00:00.000 2011-10-29 00:00:00.000
4 2011-10-29 00:00:00.000 2011-11-15 00:00:00.000
Here , I have to compare the start_date and end_date on the two different line and create a view out of it.
(If the start_date is less than the previous end_date , then criteria is set to 1).
Well it should compare 2011-10-26 00:00:00.000 for 3 and 2011-10-27 00:00:00.000 on 2 for 30 days
Number start_date end_date Criteria
----- ----------- ---------------- ------------
1 2011-06-07 00:00:00.000 2011-07-10 00:00:00.000 0
2 2011-10-11 00:00:00.000 2011-10-11 00:00:00.000 0
3 2011-10-26 00:00:00.000 2011-10-29 00:00:00.000 1
4 2011-10-30 00:00:00.000 2011-11-15 00:00:00.000 1
I m confused how should I proceed with this.
Any help would be helpful !!!!
Thanks !!!
The most straightforward way to do this is to use a subquery:
select A.number, a.start_date, a.end_date,
CASE WHEN start_date < dateadd(d,30,(select TOP(1) b.end_date
from mytable B
where B.number < A.number
order by B.number desc)) then 1 else 0 end Criteria
from mytable A
Note: If the start date is the 29th day following the previous row's end date, Criteria becomes 1. By the 30th day onwards, it is 0. Tweak the 30 in the query as required.
Sample:
create table mytable (
Number int primary key,
start_date datetime,
end_date datetime);
insert mytable
select 1, '2011-06-07', '2011-07-10' union all
select 2, '2011-10-11', '2011-10-27' union all
select 3, '2011-10-26', '2011-10-29' union all
select 4, '2011-10-29', '2011-11-15'
Result:
number start_date end_date Criteria
1 2011-06-07 00:00:00.000 2011-07-10 00:00:00.000 0
2 2011-10-11 00:00:00.000 2011-10-27 00:00:00.000 0
3 2011-10-26 00:00:00.000 2011-10-29 00:00:00.000 1
4 2011-10-29 00:00:00.000 2011-11-15 00:00:00.000 0
Try using case like this:
create view vDates as
select Number,start_date,end_date,
case
when start_date<end_date
then 0
else 1
end as Criteria
from tab
SQL Fiddle Demo
A more readable way is create a function and send the correct dates:
Function:
create function [dbo].[CompareDates] (
#START_DATE datetime,
#PREVIOUS_END_DATE datetime
)
RETURNS int
AS
BEGIN
if #START_DATE < #PREVIOUS_END_DATE
return 1
return 0
END
Query (using subquery):
declare #dates table
(
number int,
start datetime,
end_date datetime
)
insert into #dates values
(1, '2011-06-07 00:00:00.000', '2011-07-10 00:00:00.000'),
(2, '2011-10-11 00:00:00.000', '2011-10-27 00:00:00.000'),
(3, '2011-10-26 00:00:00.000', '2011-10-29 00:00:00.000'),
(4, '2011-10-29 00:00:00.000', '2011-11-15 00:00:00.000')
select *, dbo.CompareDates(dates.end_date, dates.previous_end_date) from
(
select number, start, end_date,
(select TOP 1 end_date
from #dates d2
where d2.number < d1.number
order by d2.number desc) as previous_end_date
from #dates d1
) dates
I need to create a function in TSQL that will move the date to Monday if the date passed is either a Saturday or Sunday only.
For example:
5/6/2012 should return 5/7/2012
5/12/2012 should return 5/14/2012
If the date is not a Saturday or Sunday, return the input date
This will give you the Monday following if the date is a Saturday or Sunday; otherwise, it will give you the date you provided.
DECLARE #Date DATETIME; SET #Date = GETDATE();
SELECT
CASE (##DATEFIRST + DATEPART(dw, #Date)) % 7
WHEN 0 THEN DATEADD(day, 2, #Date) -- Saturday
WHEN 1 THEN DATEADD(day, 1, #Date) -- Sunday
ELSE #Date
END AS Weekday
EDIT: Included Conrad Frix's solution to the ##DATEFIRST issue.
You can use the DatePart function in T-SQL. For each date, you can extract day component, and if it's a Saturday, increment the date by two days. If it's Sunday, increment the date by one day. You can use DateAdd to increment a date.
Depending upon your SET DATEFIRST options (US English default is 7, for Sunday = 1):
CASE
WHEN DATEPART(weekday, #dt) = 1 -- Sunday
THEN DATEADD(day, 1, #dt)
WHEN DATEPART(weekday, #dt) = 7 -- Saturday
THEN DATEADD(day, 2, #dt)
ELSE
#dt
END
A version that is not depending on set datefirst
select dateadd(day,
case datediff(day, '17530101', #D) % 7
when 5 then 2
when 6 then 1
else 0
end,
#D)
Same thing perhaps prettier.
select case datediff(day, '17530101', #D) % 7
when 5 then dateadd(day, 2, #D)
when 6 then dateadd(day, 1, #D)
else #D
end
The constant 17530101 is a Monday and works for datetime. If you are using date you can use 00010101 instead.
How about this:
SELECT CASE datepart(dw, #date) WHEN 7 THEN #date + 2 WHEN 1 THEN #date + 1 ELSE #date END
This should do it for you. Basically adds 2 days on Saturday or 1 day on Sunday to move the sample date to Monday
DECLARE #Temp TABLE
(
dtSample DATETIME
)
INSERT INTO #Temp VALUES ('5/1/2012')
INSERT INTO #Temp VALUES ('5/2/2012')
INSERT INTO #Temp VALUES ('5/3/2012')
INSERT INTO #Temp VALUES ('5/4/2012')
INSERT INTO #Temp VALUES ('5/5/2012')
INSERT INTO #Temp VALUES ('5/6/2012')
INSERT INTO #Temp VALUES ('5/7/2012')
INSERT INTO #Temp VALUES ('5/8/2012')
INSERT INTO #Temp VALUES ('5/9/2012')
INSERT INTO #Temp VALUES ('5/10/2012')
INSERT INTO #Temp VALUES ('5/11/2012')
INSERT INTO #Temp VALUES ('5/12/2012')
INSERT INTO #Temp VALUES ('5/13/2012')
INSERT INTO #Temp VALUES ('5/14/2012')
SELECT
dtSample
,CASE WHEN DATEPART(WEEKDAY, dtSample) = 7
THEN dtSample + 2
ELSE
CASE WHEN DATEPART(WEEKDAY, dtSample) = 1
THEN dtSample + 1
ELSE dtSample
END
END AS dtConverted
FROM #Temp
Results:
dtSample dtConverted
2012-05-01 00:00:00.000 2012-05-01 00:00:00.000
2012-05-02 00:00:00.000 2012-05-02 00:00:00.000
2012-05-03 00:00:00.000 2012-05-03 00:00:00.000
2012-05-04 00:00:00.000 2012-05-04 00:00:00.000
2012-05-05 00:00:00.000 2012-05-07 00:00:00.000
2012-05-06 00:00:00.000 2012-05-07 00:00:00.000
2012-05-07 00:00:00.000 2012-05-07 00:00:00.000
2012-05-08 00:00:00.000 2012-05-08 00:00:00.000
2012-05-09 00:00:00.000 2012-05-09 00:00:00.000
2012-05-10 00:00:00.000 2012-05-10 00:00:00.000
2012-05-11 00:00:00.000 2012-05-11 00:00:00.000
2012-05-12 00:00:00.000 2012-05-14 00:00:00.000
2012-05-13 00:00:00.000 2012-05-14 00:00:00.000
2012-05-14 00:00:00.000 2012-05-14 00:00:00.000
Use a combination of DATEPART and DATEADD:
select date
, CASE DATEPART(weekday, date)
WHEN 6 THEN DATEADD(day, 2, date) -- Saturday
WHEN 7 THEN DATEADD(day, 1, date) -- Sunday
ELSE date
END AS NewDate
from #dates
order by date
Sample data:
declare #dates table(date datetime);
insert into #dates values('20120401');
insert into #dates values('20120402');
insert into #dates values('20120403');
insert into #dates values('20120404');
insert into #dates values('20120405');
insert into #dates values('20120406');
insert into #dates values('20120407');
insert into #dates values('20120408');
insert into #dates values('20120409');
insert into #dates values('20120410');
Result:
date NewDate
2012-04-01 00:00:00.000 2012-04-02 00:00:00.000
2012-04-02 00:00:00.000 2012-04-02 00:00:00.000
2012-04-03 00:00:00.000 2012-04-03 00:00:00.000
2012-04-04 00:00:00.000 2012-04-04 00:00:00.000
2012-04-05 00:00:00.000 2012-04-05 00:00:00.000
2012-04-06 00:00:00.000 2012-04-06 00:00:00.000
2012-04-07 00:00:00.000 2012-04-09 00:00:00.000
2012-04-08 00:00:00.000 2012-04-09 00:00:00.000
2012-04-09 00:00:00.000 2012-04-09 00:00:00.000
2012-04-10 00:00:00.000 2012-04-10 00:00:00.000
I extended the solution provided by zimdanen on 8th May as when the start date was a friday it failed .
DECLARE #FromDate DATETIME
BEGIN
SET #FromDate='04/07/2014'
SELECT
#FromDate as [StartDate]
, CASE (##DATEFIRST + DATEPART(dw, (DATEADD(DD,3,#FromDate)))) % 7
WHEN 0 THEN DATEADD(day, 2, (DATEADD(DD,3,#FromDate))) -- Saturday
WHEN 1 THEN
CASE
WHEN DATEPART(dw,#FromDate)=5 Then DATEADD(DD,5,#FromDate) -- Thursday
ELSE DATEADD(day, 1, (DATEADD(DD,3,#FromDate))) -- Sunday
END
ELSE
CASE
WHEN DATEPART(dw,#FromDate)=6 Then DATEADD(DD,5,#FromDate) -- Friday
ELSE DATEADD(DD,3,#FromDate)
END
END AS Weekday
END