I have a data set, which looks like this:
ResourceID RequirementId ProjectID Startdate EndDate BillingPercentage
-------------------- -------------------- -------------------- ----------------------- ----------------------- ---------------------------------------
1 5066 7505 2015-09-15 00:00:00.000 2015-09-30 00:00:00.000 50
2 4748 7499 2015-09-10 00:00:00.000 2015-09-20 00:00:00.000 50
I want to calculate range and corresponding billing % for that particular month my query is:
INSERT INTO #DateTimeline
SELECT #MonthStartDate AS OSTARTDATE,#MonthEndDate AS OENDDATE,0
INSERT INTO #DateTimeline
SELECT Startdate AS OSTARTDATE,EndDate AS OENDDATE,BillingPercentage From #RESOURCE_UNBILLED Order by Startdate
INSERT INTO #DateTimeline
SELECT EndDate AS OSTARTDATE,EndDate AS OENDDATE,BillingPercentage From #RESOURCE_UNBILLED Order by Startdate
And data looks like following:
SerialNo OSTARTDATE OENDDATE BillingPercentage
----------- ----------------------- ----------------------- ---------------------------------------
1 2015-09-01 00:00:00.000 2015-09-30 00:00:00.000 0
2 2015-09-10 00:00:00.000 2015-09-20 00:00:00.000 50
3 2015-09-15 00:00:00.000 2015-09-30 00:00:00.000 50
4 2015-09-20 00:00:00.000 2015-09-20 00:00:00.000 50
5 2015-09-30 00:00:00.000 2015-09-30 00:00:00.000 50
I want to retrive data like following
OSTARTDATE OENDDATE BillingPercentage
----------- ----------------------- ----------------------- ---------------------------------------
2015-09-01 00:00:00.000 2015-09-10 00:00:00.000 0
2015-09-10 00:00:00.000 2015-09-15 00:00:00.000 50
2015-09-15 00:00:00.000 2015-09-20 00:00:00.000 100
2015-09-20 00:00:00.000 2015-09-30 00:00:00.000 50
Please suggest how can I get this also can I use pivot here?
Use a table variable to store your #dateStamps with columns: SerialNo, OSTARTDATE and OENDDATE.
Try this query:
SELECT d.SerialNo, d.OSTARTDATE, d.OENDDATE
, ( SELECT SUM(t.BillingPercentage)
FROM yourTable t
WHERE d.OENDDATE BETWEEN t.Startdate AND t.EndDate
OR d.OSTARTDATE BETWEEN t.Startdate AND t.EndDate
OR (d.OSTARTDATE > t.Startdate AND d.OENDDATE < t.EndDate)
) AS BillingPercentage
FROM
#dateStamps d
My complete code is:
DECLARE #DatePart as int = 5
;WITH dateStamps AS (
SELECT 1 As SerialNo, CAST('2015-' + CONVERT(varchar, MONTH(MIN(t.Startdate))) + '-01 00:00:00.000' As datetime) AS OSTARTDATE
, CAST('2015-' + CONVERT(varchar, MONTH(MIN(t.Startdate))) + '-01 00:00:00.000' As datetime) + (#DatePart - 1) AS OENDDATE
FROM yourTable t
UNION ALL
SELECT ds.SerialNo + 1, ds.OSTARTDATE + #DatePart, ds.OSTARTDATE + (#DatePart * 2 - 1)
FROM dateStamps ds
WHERE MONTH(OSTARTDATE + #DatePart) <= MONTH(ds.OSTARTDATE)
)
SELECT d.SerialNo, d.OSTARTDATE, d.OENDDATE
, ( SELECT SUM(t.BillingPercentage)
FROM t
WHERE d.OENDDATE BETWEEN t.Startdate AND t.EndDate
OR d.OSTARTDATE BETWEEN t.Startdate AND t.EndDate
OR (d.OSTARTDATE > t.Startdate AND d.OENDDATE < t.EndDate)
) AS BillingPercentage
FROM
dateStamps d
Related
I have a sample table below which shows the ticket number, time when the ticket was opened and time when it was closed.
TKTNUM OPEN_DATE CLOSE_DATE
1234 12-Mar-19 08:36 14-Mar-19 08:36
1235 13-Mar-19 08:36 15-Mar-19 08:36
1236 14-Mar-19 08:36 16-Mar-19 08:36
1237 15-Mar-19 08:36
1238 16-Mar-19 08:36
1239 17-Mar-19 08:36
1240 18-Mar-19 08:36 20-Mar-19 08:36
1241 19-Mar-19 08:36 20-Mar-19 08:36
1242 20-Mar-19 08:36 21-Mar-19 08:36
I need to count the number of open/closed tickets on a given day...
DATE OPEN CLOSED
12-Mar-19 08:36 1 0
13-Mar-19 08:36 2 0
14-Mar-19 08:36 2 1
15-Mar-19 08:36 2 2
16-Mar-19 08:36 2 3
17-Mar-19 08:36 3 3
18-Mar-19 08:36 4 3
19-Mar-19 08:36 5 3
20-Mar-19 08:36 4 5
Any help is greatly appreciated. Thanks
Used the query(c/o Tejash) below on a sample job_history table
EMPLOYEE_ID START_DATE END_DATE JOB_ID DEPARTMENT_ID
----------- -------------------- -------------------- ---------- -------------
200 17/SEP/1995 00:00:00 17/JUN/2001 00:00:00 AD_ASST 90
101 21/SEP/1997 00:00:00 27/OCT/2001 00:00:00 AC_ACCOUNT 110
102 13/JAN/2001 00:00:00 24/JUL/2006 00:00:00 IT_PROG 60
101 28/OCT/2001 00:00:00 15/MAR/2005 00:00:00 AC_MGR 110
200 01/JUL/2002 00:00:00 31/DEC/2006 00:00:00 AC_ACCOUNT 90
201 17/FEB/2004 00:00:00 19/DEC/2007 00:00:00 MK_REP 20
114 24/MAR/2006 00:00:00 31/DEC/2007 00:00:00 ST_CLERK 50
176 24/MAR/2006 00:00:00 31/DEC/2006 00:00:00 SA_REP 80
176 01/JAN/2007 00:00:00 31/DEC/2007 00:00:00 SA_MAN 80
122 01/JAN/2007 00:00:00 31/DEC/2007 00:00:00 ST_CLERK 50
With dates(dt)
As (Select mindt + level - 1 from
(Select min(start_date) mindt, max(end_date) maxdt from job_history)
Connect by level <= maxdt - mindt + 1)
Select dt,
sum(case when dt between start_date and coalesce(end_date,dt) then 1 end) as startdate,
Sum(case when dt >= end_date then 1 end) as enddate
From dates cross join job_history
Group by dt
Order by dt desc
On 17/JUN/2001, the query gave
DT STARTDATE ENDDATE
-------------------- ---------- ----------
31/DEC/2007 00:00:00 3 10
<SNIPPED>
17/JUN/2001 00:00:00 3 1
Instead of
DT STARTDATE ENDDATE
-------------------- ---------- ----------
31/DEC/2007 00:00:00 3 10
<SNIPPED>
17/JUN/2001 00:00:00 2 1
Tried to edit the query and now its giving me
DT STARTDATE ENDDATE
-------------------- ---------- ----------
31/DEC/2007 00:00:00 <<< 10
<snipped>
18/JUN/2001 00:00:00 2 1
17/JUN/2001 00:00:00 2 <<< 1
16/JUN/2001 00:00:00 3 1
You can use dates as cte for total days and join it again with same table as following:
With dates(dt)
As
(
Select mindt + level - 1 from
(Select min(open_date) mindt, max(open_dt) maxdt from your_table)
Connect by level <= maxdt - mindt + 1
)
Select dt,
sum(case when dt between open_date and coalesce(close_date,dt) then 1 end) as open,
Sum(case when dt >= close_date then 1 end) as closed
From dates cross join your_table
Group by dt;
Cheers!!
You can unpivot and aggregate:
select dte, sum(is_open) as num_opens, sum(is_close) as num_closes
from ((select open_date as dte, 1 as is_open, 0 as is_close
from t
) union all
(select close_date, 0 as is_open, 1 as is_close
from t
)
) t
group by dte
order by dte;
Note: It is probably a good idea to truncate the date so it has no time component:
select trunc(dte), sum(is_open) as num_opens, sum(is_close) as num_closes
from ((select open_date as dte, 1 as is_open, 0 as is_close
from t
) union all
(select close_date, 0 as is_open, 1 as is_close
from t
)
) t
where dte is not null
group by trunc(dte)
order by trunc(dte);
And in Oracle 12C you can use a lateral join for this:
select trunc(dte), sum(is_open), sum(is_close)
from t cross join lateral
(select t.open_date as dte, 1 as is_open, 0 as is_close from dual union all
select t.close_date, 0 as is_open, 1 as is_close from dual
) t
group by trunc(dte)
order by trunc(dte);
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 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 have the below input
ID Activity Date
1 gardening 2011-01-01 00:00:00.000
1 gardening 2011-02-01 00:00:00.000
2 cooking 2011-03-01 00:00:00.000
2 cooking 2011-04-01 00:00:00.000
2 cooking 2011-05-01 00:00:00.000
1 gardening 2011-06-01 00:00:00.000
1 gardening 2011-07-01 00:00:00.000
The ddl is as under
Declare #t table(ID int,Activity Varchar(50),[Date] DATETIME)
Insert into #t Select 1,'gardening','01/01/2011' union all Select 1,'gardening','02/01/2011'
union all Select 2,'cooking','03/01/2011' union all Select 2,'cooking','04/01/2011'
union all Select 2,'cooking','05/01/2011' union all Select 1,'gardening','06/01/2011'
union all Select 1,'gardening','07/01/2011'
select * from #t
Expected output
ID ACTIVITY INITIAL_DATE END_DATE
1 gardening 01/01/2011 02/01/2011
1 gardening 02/01/2011 06/01/2011
1 gardening 06/01/2011 07/01/2011
2 cooking 03/01/2011 04/01/2011
2 cooking 04/01/2011 05/01/2011
So far I have done
;with cte as(Select Rn= ROW_NUMBER() Over(order by ID,[Date]),* from #t)
,cte2 as(
Select Rn
,ID,Activity,InitialDate =[Date],EndDate = [Date]
from cte where Rn =1
union all
Select c1.Rn
,c1.ID,c1.Activity,c1.Date,c1.Date
from cte2 c2
join cte c1
on c1.rn = c2.Rn+1
)
select ID,Activity,InitialDate,EndDate from cte2
but the output is not correct
ID Activity InitialDate EndDate
1 gardening 2011-01-01 00:00:00.000 2011-01-01 00:00:00.000
1 gardening 2011-02-01 00:00:00.000 2011-02-01 00:00:00.000
1 gardening 2011-06-01 00:00:00.000 2011-06-01 00:00:00.000
1 gardening 2011-07-01 00:00:00.000 2011-07-01 00:00:00.000
2 cooking 2011-03-01 00:00:00.000 2011-03-01 00:00:00.000
2 cooking 2011-04-01 00:00:00.000 2011-04-01 00:00:00.000
2 cooking 2011-05-01 00:00:00.000 2011-05-01 00:00:00.000
Help needed
;with cte as
(
select *,
row_number() over(partition by ID order by [Date]) as rn
from #t
)
select C1.ID,
C1.Activity,
C1.[Date] as INITIAL_DATE,
C2.[Date] as END_DATE
from cte as C1
inner join cte as C2
on C1.ID = C2.ID and
C1.rn + 1 = C2.rn
order by C1.ID, C1.[Date]
try this -
in oracle it is giving desired output..
please check for respective sql server function for lead () in oracle database
with cte as(Select * from #t)
(
SELECT * from
(
SELECT id,activity,
lead(date) over(partition be id,activity order by date desc) INITIAL_DATE,
date END_DATE
from cte
order by id,activity,date
)
WHERE INITIAL_DATE is not null
)
how to display weekdays from below two days (Monday and Friday) Using SQL QUERY?
Date_From= 01/03/2011
Date_To =15/03/2011
I need output like below
Date_From Date_To
01/03/2011 01/03/2011
04/03/2011 04/03/2011 'Friday
05/03/2011 06/03/2011
07/03/2011 07/03/2011 'Monday
08/03/2011 10/03/2011
11/03/2011 11/03/2011 'Friday
12/03/2011 13/03/2011
14/03/2011 14/03/2011 'Monday
15/03/2011 15/03/2011
hoping your help
select
t1.Date_From,
t1.Date_To,
case when DATENAME(dw,t1.Date_to) IN ('friday','monday') THEN DATENAME(dw,t1.Date_to) else NULL END
from table t1
This is using Oracle. I can get the 15th to show up if I use Oracle analytic functions, but I don't know of a portable way to get the result in one row to depend on the existence of other rows. Also, due to the Cartesian product, do not use this without limiting it to a small number of rows.
select to_char(d1.d, 'DD/MM/YYYY')
, to_char(d2.d, 'DD/MM/YYYY')
, decode(d1.n, 'MONDAY', '''Monday', 'FRIDAY', '''Friday')
from (select to_date('2011-02-28') + rownum as d
, to_char(to_date('2011-02-28') + rownum, 'FMDAY') as n
from user_objects where rownum <= 15) d1
, (select to_date('2011-02-28') + rownum as d
, to_char(to_date('2011-02-28') + rownum, 'FMDAY') as n
from user_objects where rownum <= 15) d2
where d1.d <= d2.d
and d2.d - d1.d < 7
and ((d1.d = d2.d and d1.n in ('MONDAY', 'FRIDAY'))
or (d1.n = 'TUESDAY' and d2.n = 'THURSDAY')
or (d1.n = 'SATURDAY' and d2.n = 'SUNDAY'))
order by d1.d, d2.d;
This is for SQL Server 2005+.
DECLARE #Date_From datetime, #Date_To datetime;
SET #Date_From = '20110301';
SET #Date_To = '20110315';
WITH datelist AS (
SELECT
Date = #Date_From,
GroupID = 1
UNION ALL
SELECT
Date = DATEADD(day, 1, Date),
GroupID = CASE
WHEN DATENAME(dw, Date) IN ('Sunday', 'Monday', 'Thursday', 'Friday')
THEN 1
ELSE 0
END + GroupID
FROM datelist
WHERE Date < #Date_To
)
SELECT
Date_From = MIN(Date),
Date_To = MAX(Date)
FROM datelist
GROUP BY GroupID
Output:
Date_From Date_To
----------------------- -----------------------
2011-03-01 00:00:00.000 2011-03-03 00:00:00.000
2011-03-04 00:00:00.000 2011-03-04 00:00:00.000
2011-03-05 00:00:00.000 2011-03-06 00:00:00.000
2011-03-07 00:00:00.000 2011-03-07 00:00:00.000
2011-03-08 00:00:00.000 2011-03-10 00:00:00.000
2011-03-11 00:00:00.000 2011-03-11 00:00:00.000
2011-03-12 00:00:00.000 2011-03-13 00:00:00.000
2011-03-14 00:00:00.000 2011-03-14 00:00:00.000
2011-03-15 00:00:00.000 2011-03-15 00:00:00.000