Contiguous Dates - sql

Here is the table that I am working with:
MemberID MembershipStartDate MembershipEndDate
=================================================================
123 2010-01-01 00:00:00.000 2012-12-31 00:00:00.000
123 2011-01-01 00:00:00.000 2012-12-31 00:00:00.000
123 2013-05-01 00:00:00.000 2013-12-31 00:00:00.000
123 2014-01-01 00:00:00.000 2014-12-31 00:00:00.000
123 2015-01-01 00:00:00.000 2015-03-31 00:00:00.000
What I want is to create one row that shows continuous membership,
and a second row if the membership breaks by more than 2 days, with a new start and end date..
So the output I am looking for is like:
MemberID MembershipStartDate MembershipEndDate
=================================================================
123 2010-01-01 00:00:00.000 2012-12-31 00:00:00.000
123 2013-05-01 00:00:00.000 2015-03-31 00:00:00.000
There is a memberID field attached to these dates which is how they are grouped.

I've had to deal with this kind of thing before
I use something like this
USE tempdb
--Create test Data
DECLARE #Membership TABLE (MemberID int ,MembershipStartDate date,MembershipEndDate date)
INSERT #Membership
(MemberID,MembershipStartDate,MembershipEndDate)
VALUES (123,'2010-01-01','2012-12-31'),
(123,'2011-01-01','2012-12-31'),
(123,'2013-05-01','2013-12-31'),
(123,'2014-01-01','2014-12-31'),
(123,'2015-01-01','2015-03-31')
--Create a table to hold all the dates that might be turning points
DECLARE #SignificantDates Table(MemberID int, SignificantDate date, IsMember bit DEFAULT 0)
--Populate table with the start and end dates as well as the days just before and just after each period
INSERT #SignificantDates (MemberID ,SignificantDate)
SELECT MemberID, MembershipStartDate FROM #Membership
UNION
SELECT MemberID,DATEADD(day,-1,MembershipStartDate ) FROM #Membership
UNION
SELECT MemberID,MembershipEndDate FROM #Membership
UNION
SELECT MemberID,DATEADD(day,1,MembershipEndDate) FROM #Membership
--Set the is member flag for each date that is covered by a membership
UPDATE sd SET IsMember = 1
FROM #SignificantDates sd
JOIN #Membership m ON MembershipStartDate<= SignificantDate AND SignificantDate <= MembershipEndDate
--To demonstrate what we're about to do, Select all the dates and show the IsMember Flag and the previous value
SELECT sd.MemberID, sd.SignificantDate,sd.IsMember, prv.prevIsMember
FROM
#SignificantDates sd
JOIN (SELECT
MemberId,
SignificantDate,
IsMember,
Lag(IsMember,1) OVER (PARTITION BY MemberId ORDER BY SignificantDate desc) AS prevIsMember FROM #SignificantDates
) as prv
ON sd.MemberID = prv.MemberID
AND sd.SignificantDate = prv.SignificantDate
ORDER BY sd.MemberID, sd.SignificantDate
--Delete the ones where the flag is the same as the previous value
delete sd
FROM
#SignificantDates sd
JOIN (SELECT MemberId, SignificantDate,IsMember, Lag(IsMember,1) OVER (PARTITION BY MemberId ORDER BY SignificantDate) AS prevIsMember FROM #SignificantDates ) as prv
ON sd.MemberID = prv.MemberID
AND sd.SignificantDate = prv.SignificantDate
AND prv.IsMember = prv.prevIsMember
--SELECT the Start date for each period of membership and the day before the following period of non membership
SELECT
nxt.MemberId,
nxt.SignificantDate AS MembershipStartDate,
DATEADD(day,-1,nxt.NextSignificantDate) AS MembershipEndDate
FROM
(
SELECT
MemberID,
SignificantDate,
LEAd(SignificantDate,1) OVER (PARTITION BY MemberId ORDER BY SignificantDate) AS NextSignificantDate,
IsMember
FROM #SignificantDates
) nxt
WHERE nxt.IsMember = 1

Related

How can I get distinct data from one col

I need to get member personal data for all our members whose subscriptions have lapsed i.e. have a subscription end date before 31/03/2020, however I want to show one member record only (distinct by membership number) ideally the most recent one
I've tried a ROW_NUMBER() solution SQL - Distinct One Col, Select Multiple other? and a cross apply solution sql distinct, getting 2 columns but I can't get it to work.
SELECT membershipnumber AS Id,
subscription.enddate
FROM [dbo].[userprofile]
INNER JOIN dbo.subscription
ON userprofile.id = subscription.userprofileid
INNER JOIN dbo.subscriptiontype
ON subscriptiontype.id = subscription.subscriptiontypeid
Output is
Id Enddate
1 2006-04-01 00:00:00.000
1 2001-04-01 00:00:00.000
1 1999-04-01 00:00:00.000
1 1998-04-01 00:00:00.000
1 2008-04-01 00:00:00.000
1 2007-04-01 00:00:00.000
1 2011-04-01 00:00:00.000
1 2005-04-01 00:00:00.000
1 2000-04-01 00:00:00.000
1 1997-04-01 00:00:00.000
2 1999-04-01 00:00:00.000
2 2012-04-01 00:00:00.000
2 2004-04-01 00:00:00.000
2 2001-04-01 00:00:00.000
2 2018-04-01 00:00:00.000
2 2009-04-01 00:00:00.000
2 2005-04-01 00:00:00.000
2 1997-04-01 00:00:00.000
Desired output
Id Enddate
1 2011-04-01 00:00:00.000
2 2018-04-01 00:00:00.000
Solved sql answer
;WITH cte
AS (SELECT membershipnumber AS Id,
subscription.enddate,
Row_number()
OVER (
partition BY membershipnumber
ORDER BY subscription.enddate DESC) AS rownumber
FROM [dbo].[userprofile]
INNER JOIN dbo.subscription
ON userprofile.id = subscription.userprofileid
INNER JOIN dbo.subscriptiontype
ON subscriptiontype.id = subscription.subscriptiontypeid
)
SELECT *
FROM cte
WHERE rownumber = 1
https://stackoverflow.com/a/6841644/5859743
Not sure if I got your question right.
but you can use DISTINCT in the SELECT, that would show only one record for each member.
SELECT DISTINCT Membershipnumber as Id
,'P' as PartyType
,'A' as Status
,case
when Name = 'Standard Membership paid annually.' and EndDate > '2020-03-31' then 'Member'
when Name = 'Lapsed subscription renewal' and EndDate > '2020-03-31' then 'Member'
when Name = '3 Year Subscription (members outside of UK and Ireland, Jersey, Guernsey and the Channel Islands)' and EndDate > '2020-03-31' then 'Overseas member'
when Name = '1 Year Subscription (members outside of UK and Ireland, Jersey, Guernsey and the Channel Islands).' and EndDate > '2020-03-31' then 'Overseas member'
when Name = 'Lapsed subscription renewal' and EndDate > '2020-03-31' then 'Member'
when Name = 'Lifetime membership' then 'Lifetime member'
when Name = 'Retired membership paid annually' and EndDate > '2020-03-31' then 'Retired member'
else 'Non member'
end As MemberType
,Title as NamePrefix
,FirstName as FirstName
,Surname as LastName
,DateOfBirth as BirthDate
,'Home' as AddressPurpose
,'Default' as CommunicationReasons
,AddressLine1
,AddressLine2
,AddressLine3
,Addressline4 as CityName
,'' as CountrySubEntityName
,Country as CountryCode
,'' as CountryName
,Postcode as PostalCode
,EmailAddress as Email
FROM [dbo].[UserProfile]
inner join dbo.Subscription on
UserProfile.Id = Subscription.UserProfileId
inner join dbo.SubscriptionType on
SubscriptionType.id = Subscription.SubscriptionTypeId```
If you are getting as above mentioned output. Then from that, your desired output will easily get using distinct.
; with cte as (
----- query which gives you above mentioned output
)
select distinct id, max(Enddate) as Enddate from cte
I suspect you want something like this:
select *
from (select . . ., -- all the columns you want
row_number() over (partition by Membershipnumber as Id order by s.Enddate) as seqnum
from [dbo].[UserProfile] up inner join
dbo.Subscription s
on up.Id = s.UserProfileId inner join
dbo.SubscriptionType st
on st.id = s.SubscriptionTypeId
) x
where seqnum = 1;

Counting rows between dates using row number?

I am trying to find the number of rows that 2 dates fall between. Basically I have an auth dated 1/1/2018 - 4/1/2018 and I need the count of pay periods those dates fall within.
Here is the data I am looking at:
create table #dates
(
pp_start_date date,
pp_end_date date
)
insert into #dates (pp_start_date,pp_end_date)
values ('2017-12-28', '2018-01-10'),
('2018-01-11', '2018-01-24'),
('2018-01-25', '2018-02-07'),
('2018-02-08', '2018-02-21'),
('2018-02-22', '2018-03-07'),
('2018-03-08', '2018-03-21'),
('2018-03-22', '2018-04-04'),
('2018-04-05', '2018-04-18');
When I run this query,
SELECT
ad.pp_start_date, ad.pp_end_date, orderby
FROM
(SELECT
ROW_NUMBER() OVER (ORDER BY pp_start_date) AS orderby, *
FROM
#dates) ad
WHERE
'2018-01-01' <= ad.pp_end_date
I somehow want to only get 7 rows. Is this even possible? Thanks in advance for any help!
EDIT - Ok so using a count(*) worked to get the number of rows but now I am trying to get the number of rows for 2 dynamic dates form another temp table but I don't see a way to relate the data.
Using the #dates temp table referenced above gives me the date data. Now using this data:
create table #stuff
([month] date,
[name] varchar(20),
units int,
fips_code int,
auth_datefrom date,
auth_dateto date)
insert into #stuff (month,name,units,fips_code,auth_datefrom,auth_dateto)
values ('2018-01-01','SMITH','50','760', '2018-01-01', '2018-04-01');
insert into #stuff (month,name,units,fips_code,auth_datefrom,auth_dateto)
values ('2018-01-01','JONES','46','193', '2018-01-01', '2018-04-01');
insert into #stuff (month,name,units,fips_code,auth_datefrom,auth_dateto)
values ('2018-01-01','DAVID','84','109', '2018-02-01', '2018-04-01');
I want to somehow create a statement that does a count of rows from the #dates table where the auth dates are referenced in the #stuff table I just can't figure out how to relate them or join them.
pp_start_date <= auth_dateto and pp_end_date >= auth_datefrom
Here is my output for #dates
pp_start_date pp_end_date
2017-12-28 2018-01-10
2018-01-11 2018-01-24
2018-01-25 2018-02-07
2018-02-08 2018-02-21
2018-02-22 2018-03-07
2018-03-08 2018-03-21
2018-03-22 2018-04-04
2018-04-05 2018-04-18
Here is my output for #stuff
month name units fips_code auth_datefrom auth_dateto
2018-01-01 SMITH 50 760 2018-01-01 2018-04-01
2018-01-01 JONES 46 193 2018-01-01 2018-04-01
2018-01-01 DAVID 84 109 2018-02-01 2018-04-01
I am trying to use the auth_datefrom and auth_dateto from #stuff to find out how many rows that is from #dates.
try this one.
SELECT ad.pp_start_date, ad.pp_end_date, orderby
from (select
row_number()over ( order by pp_start_date) as orderby, * from
#dates) ad
where ad.pp_end_date <= '2018-01-01'
or ad.pp_start_date >= '2018-01-01'
Are you looking for this?
select d.*
from #dates d
where d.startdate <= '2018-04-01' and
d.enddate >= '2018-01-01';
This returns all rows that have a date with the time period you specify.
I'm not sure what the row_number() does. If you want the count, then:
select count(*)
from #dates d
where d.startdate <= '2018-04-01' and
d.enddate >= '2018-01-01';

Find gaps in time not covered by records with start date and end date

I have a table of fee records (f_fee_item) as follows:
Fee_Item_ID int
Fee_Basis_ID int
Start_Date date
End_Date date
(irrelevant columns removed)
Assume that records for the same Fee_Basis_ID won't overlap.
I need to find the Start_Date and End_Date of each gap in the fee records for each Fee_Basis_ID between a supplied #Query_Start_Date and #Query_End_Date. I need this data to calculate fee accruals for all periods where fees have not been charged.
I also need the query to return a record if there are no fee records at all for a given Fee_Basis_ID (Fee_Basis_ID is a foreign key to D_Fee_Basis.Fee_Basis_ID if that helps).
For example:
#Query_Start_Date = '2011-01-01'
#Query_Start_Date = '2011-09-30'
D_Fee_Basis:
F_Fee_Item
1
2
3
F_Fee_Item:
Fee_Item_ID Fee_Basis_ID Start_Date End_Date
1 1 2011-01-01 2011-03-31
2 1 2011-04-01 2011-06-30
3 2 2011-01-01 2011-03-31
4 2 2011-05-01 2011-06-30
Required Results:
Fee_Basis_ID Start_Date End_Date
1 2011-07-01 2011-09-30
2 2011-04-01 2011-04-30
2 2011-07-01 2011-09-30
3 2011-01-01 2011-09-30
I've bee trying different self-joins for days trying to get it working but with no luck.
Please help!!
Here is a solution:
declare #Query_Start_Date date= '2011-01-01'
declare #Query_End_Date date = '2011-09-30'
declare #D_Fee_Basis table(F_Fee_Item int)
insert #D_Fee_Basis values(1)
insert #D_Fee_Basis values(2)
insert #D_Fee_Basis values(3)
declare #F_Fee_Item table(Fee_Item_ID int, Fee_Basis_ID int,Start_Date date,End_Date date)
insert #F_Fee_Item values(1,1,'2011-01-01','2011-03-31')
insert #F_Fee_Item values(2,1,'2011-04-01','2011-06-30')
insert #F_Fee_Item values(3,2,'2011-01-01','2011-03-31')
insert #F_Fee_Item values(4,2,'2011-05-01','2011-06-30')
;with a as
(-- find all days between Start_Date and End_Date
select #Query_Start_Date d
union all
select dateadd(day, 1, d)
from a
where d < #Query_end_Date
), b as
(--find all unused days
select a.d, F_Fee_Item Fee
from a, #D_Fee_Basis Fee
where not exists(select 1 from #F_Fee_Item where a.d between Start_Date and End_Date and Fee.F_Fee_Item = Fee_Basis_ID)
),
c as
(--find all start dates
select d, Fee, rn = row_number() over (order by fee, d) from b
where not exists (select 1 from b b2 where dateadd(day,1, b2.d) = b.d and b2.Fee= b.Fee)
),
e as
(--find all end dates
select d, Fee, rn = row_number() over (order by fee, d) from b
where not exists (select 1 from b b2 where dateadd(day,-1, b2.d) = b.d and b2.Fee= b.Fee)
)
--join start dates with end dates
select c.Fee Fee_Basis_ID, c.d Start_Date, e.d End_Date from c join e on c.Fee = e.Fee and c.rn = e.rn
option (maxrecursion 0)
Link for result:
https://data.stackexchange.com/stackoverflow/q/114193/

Impossible Task On Sql Calculation Where Date Is Equal

**
LOOK AT MY ANSWER WHICH IS REFERE AS NEW QUESTION ON SAME PROBLEM.
**
I have Confusion against utilize If,Else Statement against calculation of stock By date. And sort the same by date.
There is real challenge to calculate running total between equal date:
If date is equal
If date is greater than
If date is less than
My Table Schema Is:
TransID int, Auto Increment
Date datetime,
Inwards decimal(12,2)
Outward decimal(12,2)
Suppose If I have Records as Below:
TransID Date(DD/MM/YYYY) Inward Outward
1 03/02/2011 100
2 12/04/2010 200
3 03/02/2011 400
Than Result Should be:
TransID Date(DD/MM/YYYY) Inward Outward Balance
2 12/04/2010 200 -200
1 03/02/2011 100 -300
3 03/02/2011 400 100
I wants to calculate Inward - outwards = Balance and Balance count as running total as above. but the condition that it should be as per date order by Ascending
How to sort and calculate it by date and transID?
What is transact SQL IN SQL_SERVER-2000**?.
You can use a brute O(n2) approach of self-joining the table to itself, or if the table is large, it is better to iteratively calculate the balance. The choices for SQL Server 2000 are limited, but the approach I will show uses a loop that traverses the table in date, transid order rather than using cursors.
Here is a sample table for discussion
create table trans (transid int identity, date datetime, inwards decimal(12,2), outward decimal(12,2))
insert trans select '20110203', null, 100
insert trans select '20100412', null, 200
insert trans select '20110203', 400, null -- !same date as first
This is the T-SQL batch that will give you the output you require. If you merely wanted to update a balance column in the table (if it had such an extra column), change all references to #trans to the table itself.
-- fill a temp table with the new column required
select *, cast(null as decimal(12,2)) as balance
into #trans
from trans
-- create an index to aid performance
create clustered index #cix_trans on #trans(date, transid)
-- set up a loop to go through all record in the temp table
-- in preference to using CURSORs
declare #date datetime, #id int, #balance decimal(12,2)
select top 1 #date = date, #id = transid, #balance = 0
from #trans
order by date, transid
while ##ROWCOUNT > 0 begin
update #trans set #balance = balance = #balance + coalesce(inwards, -outward)
where transid = #id
-- next record
select top 1 #date = date, #id = transid
from #trans
where (date = #date and transid > #id)
or (date > #date)
order by date, transid
end
-- show the output
select *
from #trans
order by date, transid
;
-- clean up
drop table #trans;
Output
2 2010-04-12 00:00:00.000 NULL 200.00 -200.00
1 2011-02-03 00:00:00.000 NULL 100.00 -300.00
3 2011-02-03 00:00:00.000 400.00 NULL 100.00
EDIT
If you need to show the final output using the date formatted to dd/mm/yyyy, use this
-- show the output
select transid, convert(char(10), date, 103) date, inwards, outward, balance
from #trans
order by #trans.date, transid
;
Is Balance (Inward-Outward) ?
select TransID,
Date,
Inward,
Outward,
(select sum(Inward - Outward)
from tbl_name b1
where b1.TransID <= b.TransID) as RunB
from tbl_name b
order by Date desc,TransID desc
This would order by Date in descending order - if the dates are same they are ordered by TransID
Edit:
Assume a Transaction table as this
select * from Transactions
1 NULL 100.00 2010-01-01 00:00:00.000
2 NULL 200.00 2010-01-02 00:00:00.000
3 400.00 NULL 2010-01-03 00:00:00.000
4 50.00 NULL 2010-01-03 00:00:00.000
5 NULL 100.00 2010-01-04 00:00:00.000
If you do this query ie, sort by TransactionIDs you would get this!
select TransID,
Date,
isNull(Inward,0.0),
isNull(Outward,0.0),
(select sum(isNull(Inward,0.0) - isNull(Outward,0.0))
from Transactions b1
where b1.TransID <= b.TransID) as RunB
from Transactions b
order by Date asc,TransID asc
1 2010-01-01 00:00:00.000 0.00 100.00 -100.00
2 2010-01-02 00:00:00.000 0.00 200.00 -300.00
3 2010-01-03 00:00:00.000 400.00 0.00 100.00
4 2010-01-03 00:00:00.000 50.00 0.00 150.00
5 2010-01-04 00:00:00.000 0.00 100.00 50.00
Instead if you use this query - sort by date you would get this? Is this what you meant Mahesh?
select TransID,
Date,
isNull(Inward,0.0),
isNull(Outward,0.0),
(select sum(isNull(Inward,0.0) - isNull(Outward,0.0))
from Transactions b1
where b1.Date <= b.Date) as RunB
from Transactions b
order by Date asc,TransID asc
1 2010-01-01 00:00:00.000 0.00 100.00 -100.00
2 2010-01-02 00:00:00.000 0.00 200.00 -300.00
3 2010-01-03 00:00:00.000 400.00 0.00 150.00
4 2010-01-03 00:00:00.000 50.00 0.00 150.00
5 2010-01-04 00:00:00.000 0.00 100.00 50.00
The difference in queries being -> (b1.Date <= b.Date) and (b1.TransID <= b.TransID)
Take this first bit of cyberkiwi's solution:
select *, cast(null as decimal(12,2)) as balance
into #trans
from stock
and change it so the nvarchar dates from your table are converted to datetime values. That is, expand the * into the actual set of columns, replacing the date column with the converting expression.
Given the structure you've shown in your original question, it may look like this:
select
TransID,
convert(datetime, substring(Date,7,4) + substring(Date,4,2) + substring(Date,1,2)) as Date,
Inward,
Outward,
cast(null as decimal(12,2)) as balance
into #trans
from stock
Leave the rest of the script untouched.
Now this is Solution with date in format dd/MM/yyyy of above question.
select *, cast(null as decimal(12,2)) as balance
into #trans
from stock
-- create an index to aid performance
create clustered index #cix_trans on #trans(date, transid)
--set up a loop to go through all record in the temp table
-- in preference to using CURSORs
declare #date datetime, #id int, #balance decimal(12,2)
select top 1 #date = date, #id = transid, #balance = 0
from #trans
order by date, transid
while ##ROWCOUNT > 0 begin
update #trans set #balance = balance = #balance + coalesce(input, -output)
where transid = #id
-- next record
select top 1 #date = date, #id = transid
from #trans
where (date = #date and transid > #id)
or (date > #date)
order by date, transid
end
-- show the output
select
transID,
date= convert(varchar,convert(datetime,date,103),103),
input,
output,
balance
from #trans
order by convert(datetime,date,103), transID
-- clean up
drop table #trans;

Add Missing Date Range to Result Record Set

I have a table containing the working hours for the company. We define the range of the dates and the number of hours for the range.
The number of working hours which is not in the defined range is 9.5 hours.
I want to have the non-defined range with the value of 9.5 added to the result record set.
how should I make the query to get this result?
The table definition and added records:
IF OBJECT_ID ('dbo.tbl_WorkingHours') IS NOT NULL
DROP TABLE dbo.tbl_WorkingHours
GO
CREATE TABLE dbo.tbl_WorkingHours
(
Startdate DATETIME NOT NULL,
EndDate DATETIME NOT NULL,
HoursDefined FLOAT NULL,
Description VARCHAR (255) NULL,
PRIMARY KEY (Startdate,EndDate)
)
INSERT INTO dbo.tbl_WorkingHours
(Startdate,EndDate,HoursDefined,Description)
VALUES
('3/4/2010','3/29/2010',7,'')
INSERT INTO dbo.tbl_WorkingHours
(Startdate,EndDate,HoursDefined,Description)
VALUES
('5/4/2010','5/29/2010',8,'')
The Result of Select * :
Startdate | EndDate | HoursDefined | Description
----------------------------------------------------
3/4/2010 3/29/2010 7
5/4/2010 5/29/2010 8
My desired record set:
Startdate | EndDate | HoursDefined | Description
----------------------------------------------------
1/1/1900 3/3/2010 9.5
3/4/2010 3/29/2010 7
3/30/2010 5/3/2010 9.5
5/4/2010 5/29/2010 8
5/30/2010 1/1/2050 9.5
The below assumes it is not possible to have overlapping ranges or two defined ranges that are contiguous but held as separate rows.
WITH wh AS
(
SELECT Startdate, EndDate, HoursDefined, Description,
ROW_NUMBER() over (order by startdate) as rn
FROM tbl_WorkingHours
)
SELECT Startdate, EndDate, HoursDefined, Description
FROM wh
UNION ALL
SELECT ISNULL(dateadd(day,1,w1.EndDate),'19000101'),
ISNULL(dateadd(day,-1,w2.StartDate),'20500101') , 9.5 AS HoursDefined,''
FROM wh w1 FULL OUTER JOIN wh w2
ON w2.rn = w1.rn+1
ORDER BY Startdate
try something like this:
DECLARE #tbl_WorkingHours table (Startdate DATETIME NOT NULL
,EndDate DATETIME NOT NULL
,HoursDefined FLOAT NULL
,Description VARCHAR (255) NULL
,PRIMARY KEY (Startdate,EndDate)
)
INSERT INTO #tbl_WorkingHours (Startdate,EndDate,HoursDefined,Description) VALUES ('3/4/2010','3/29/2010',7,'')
INSERT INTO #tbl_WorkingHours (Startdate,EndDate,HoursDefined,Description) VALUES ('5/4/2010','5/29/2010',8,'')
;WITH OrderedRows AS
( SELECT
Startdate,EndDate,HoursDefined,Description, ROW_NUMBER() OVER (ORDER BY Startdate,EndDate) AS RowNumber
FROM #tbl_WorkingHours
)
SELECT --before rows
CONVERT(datetime,'1/1/1900') AS Startdate,ISNULL(MIN(Startdate),CONVERT(datetime,'1/2/2050'))-1 AS EndDate,9.5 AS HoursDefined, CONVERT(VARCHAR (255),'') AS Description
FROM #tbl_WorkingHours
UNION ALL
SELECT --actual rows
Startdate,EndDate,HoursDefined,Description
FROM #tbl_WorkingHours
UNION ALL
SELECT --between rows
a.EndDate+1,b.Startdate-1,9.5,''
FROM OrderedRows a
INNER JOIN OrderedRows b ON a.RowNumber=b.RowNumber-1
UNION ALL
SELECT --after rows
ISNULL(MAX(EndDate),CONVERT(datetime,'1/1/2050')) AS Startdate,CONVERT(datetime,'1/2/2050')-1 AS EndDate,9.5 AS HoursDefined, CONVERT(VARCHAR (255),'') AS Description
FROM #tbl_WorkingHours
ORDER BY Startdate,EndDate
OUTPUT:
Startdate EndDate HoursDefined Description
----------------------- ----------------------- ---------------------- -----------
1900-01-01 00:00:00.000 2010-03-03 00:00:00.000 9.5
2010-03-04 00:00:00.000 2010-03-29 00:00:00.000 7
2010-03-30 00:00:00.000 2010-05-03 00:00:00.000 9.5
2010-05-04 00:00:00.000 2010-05-29 00:00:00.000 8
2010-05-29 00:00:00.000 2050-01-01 00:00:00.000 9.5
(5 row(s) affected)