SSRS loop over select by months - sql-server

I am creating report in SSRS that should show event duration in a month. This report should do it 12 time for every calendar month separately. At the moment my select has 12 hardcoded selects, for every month each. How can I do this with one select repeated 12 times and just iterated start and end times, either in SQL language (applicable as a view) or even better from SSRS? Thank you.
SELECT DATEDIFF(mi, '2014-01-01 00:00:00.000', end_date) AS total_event
FROM MY_TABLE
WHERE (start_date <= '2014-01-01 00:00:00.000') AND (end_date BETWEEN '2014-01-01 00:00:00.000' AND '2014-02-01 00:00:00.000')
UNION ALL
SELECT DATEDIFF(mi, start_date, '2014-02-01 00:00:00.000') AS total_event
FROM MY_TABLE
WHERE (end_date >= '2014-02-01 00:00:00.000') AND (start_date BETWEEN '2014-01-01 00:00:00.000' AND '2014-02-01 00:00:00.000')
UNION ALL
SELECT DATEDIFF(mi, '2014-01-01 00:00:00.000', '2014-02-01 00:00:00.000') AS total_event
FROM MY_TABLE
WHERE (start_date <= '2014-01-01 00:00:00.000') AND (end_date >= '2014-02-01 00:00:00.000')
UNION ALL
SELECT DATEDIFF(mi, start_date, end_date) AS total_event
FROM MY_TABLE
WHERE (start_date BETWEEN '2014-01-01 00:00:00.000' AND '2014-02-01 00:00:00.000') AND (end_date BETWEEN '2014-01-01 00:00:00.000' AND '2014-02-01 00:00:00.000')

try using below script
declare #start datetime
declare #end datetime
set #start = '2014-01-01' --firstDay year
set #end = '2014-12-31' --last Day of year
;with cte as
(
select #start firstday, DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,DATEADD(month, DATEDIFF(month, 0, #start), 0))+1,0)) lastday, 1 MM
union all
select DATEADD(month, DATEDIFF(month, 0, lastday + 1), 0) , DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,DATEADD(month, DATEDIFF(month, 0, lastday + 1), 0))+1,0)), MM + 1
from cte
where lastday < #end
)
SELECT * FROM CTE C
--LEFT OUTER JOIN MY_TABLE M ON (M.start_date <= firstday) AND (end_date BETWEEN firstday AND lastday)
just un-comment last line
--LEFT OUTER JOIN MY_TABLE M ON (M.start_date <= firstday) AND (end_date BETWEEN firstday AND lastday)

You could try this:
SELECT
DATEADD(MONTH, DATEDIFF(MONTH, 0, start_date), 0) AS [month], DATEDIFF(MINUTE, DATEADD(MONTH, DATEDIFF(MONTH, 0, start_date), 0), end_date) AS total_event
FROM
MY_TABLE
WHERE
YEAR(start_date) = 2014
ORDER BY
[month];

Related

How to get data of current date using sum in SQL?

I'm working on a SQL query trying to fetch sum data for the current day/date. Can anyone have a look at my query, and find me a working solution?
SELECT SUM(amount)
FROM tbl_expense_record
WHERE dateonly = CAST(GETDATE() AS Date)
But I get data when mentioning a specific date in where condition like
SELECT SUM(amount) AS total
FROM tbl_expense_record
WHERE dateonly = '2020-06-12'
I want the a code to auto pick current date. Also I would like to fetch sum of ranged dates like a whole week, and a month!
select datename(month, '2020-06-12'), datename(month, getdate());
--1week
SELECT SUM(amount) AS total
FROM tbl_expense_record
WHERE dateonly >= dateadd(week, -1, cast(getdate() as date))
and dateonly <= cast(getdate() as date)
--1month
SELECT SUM(amount) AS total
FROM tbl_expense_record
WHERE dateonly >= dateadd(month, -1, cast(getdate() as date))
and dateonly <= cast(getdate() as date)
--build muscle memory (it is always safe to check for < date+1 instead of <= date)
--1month
SELECT SUM(amount) AS total
FROM tbl_expense_record
WHERE dateonly >= dateadd(month, -1, cast(getdate() as date))
and dateonly < dateadd(day, 1, cast(getdate() as date));
--6months
SELECT SUM(amount) AS total
FROM tbl_expense_record
WHERE dateonly >= dateadd(month, -6, cast(getdate() as date))
and dateonly < dateadd(day, 1, cast(getdate() as date));
if not exists
(
select *
FROM tbl_expense_record
WHERE dateonly >= dateadd(month, -1, cast(getdate() as date))
and dateonly < dateadd(day, 1, cast(getdate() as date))
)
begin
select 'no rows within the last month'
end
else
begin
select 'there are rows within the last month';
end;
Examples:
declare #tbl_expense_record table(dateonly date, amount decimal(9,2));
insert into #tbl_expense_record
values ('20200501', 10), ('20200612', 10), ('20200613', 11), ('20200614', 12),
('20200710', 5), ('20200720', 6), ('20200820', 20), ('20200825', 30),
('20201102', 1), ('20201110', 2), ('20201120', 3);
--aggregation per month, for all rows
select year(dateonly) as _year, month(dateonly) as _month, sum(amount) as sum_amount_per_month, count(*) as rows_per_month
from #tbl_expense_record
group by year(dateonly), month(dateonly);
--aggregation per iso-week
select year(dateonly) as _year, datepart(iso_week, dateonly) as _isoweek, sum(amount) as sum_amount_per_isoweek, count(*) as rows_per_isoweek
from #tbl_expense_record
group by year(dateonly), datepart(iso_week, dateonly);
--aggregation per month, for all rows with a dateonly that falls in the last month
--check the difference between aggregation per month earlier and this..
--filter rows first == where .... and then aggregate
--there are two rows with dateonly > 06 november (the row at 05 is filtered out by the where clause)
select year(dateonly) as _year, month(dateonly) as _month, sum(amount) as sum_amount_per_month, count(*) as rows_per_month
from #tbl_expense_record
where dateonly >= dateadd(month, -1, cast(getdate() as date))
and dateonly < dateadd(day, 1, cast(getdate() as date))
group by year(dateonly), month(dateonly);
--aggregate per week diff from today/getdate()
select
datediff(week, getdate(), dateonly) as week_diff_from_today,
dateadd(day,
--datepart(weekday..) is used...account for ##datefirst setting / set datefirst
1-(##datefirst+datepart(weekday, dateadd(week, datediff(week, getdate(), dateonly), cast(getdate() as date))))%7,
dateadd(week, datediff(week, getdate(), dateonly), cast(getdate() as date)))
as startofweek,
dateadd(day, 6, --add 6 days to startofweek
dateadd(day,
--datepart(weekday..) is used...account for ##datefirst setting / set datefirst
1-(##datefirst+datepart(weekday, dateadd(week, datediff(week, getdate(), dateonly), cast(getdate() as date))))%7,
dateadd(week, datediff(week, getdate(), dateonly), cast(getdate() as date)))
) as endofweek,
sum(amount) as sum_amount, count(*) as rows_within_week
from #tbl_expense_record
group by datediff(week, getdate(), dateonly);

Filling table with weeks of the year skips first week of 2021

So, I am using the following snippet on a procedure, which fills me a temporary table with the first day of each year's week, the week number and month name.
However, when I reach week 53, of 2020, it jumps to week 2 of 2021. This happens because the first of january is in the so called week 53 (which is correct), but it should also be creating another row with the first week of january 2021 (even with the sunday as being in 2020, as it should).
Snippet:
SET DATEFIRST 7
DECLARE #tblSundays TABLE (
[year] INT
,[month] INT
,[week] INT
,[date] DATETIME
)
DECLARE #DateFrom DATETIME = '2020-12-12'
,#DateTo DATETIME = '2021-06-06';
--select #DateFrom,#DateTo;
WITH CTE (dt)
AS (
SELECT #DateFrom
UNION ALL
SELECT DATEADD(d, 1, dt)
FROM CTE
WHERE dt < #DateTo
)
INSERT INTO #tblSundays
SELECT datepart(year, dt)
,datepart(month, dt)
,datepart(week, dt)
,dt
FROM CTE
WHERE datepart("dw", dt) = 1
OPTION (MAXRECURSION 1000)
;
select * from #tblSundays
Is there any way that I can do this within this snippet, or should I create a manual verification?
Thanks!
You should do a couple of little tricks to set week 1 to the first Sunday of the year (tested for the next 30 years):
set datefirst 7
declare #tblSundays table ([year] int, [month] int, [week] int, [date] date)
declare #DateFrom datetime = '20201212', #DateTo datetime = '20510112';
-- Get the next closest Sunday
select #DateFrom = dateAdd(wk, dateDiff(wk, 0, #datefrom - 1 ), 0) + 6
with CTE (dt) as (
select #DateFrom
union all
select dateAdd(dd, 7, dt) from CTE where dt < #DateTo
)
insert into #tblSundays
select datePart(yy, dt),
datePart(mm, dt),
datePart(wk, dt - (1 + (datePart(dy, dt) + 5) % 7) % 7),
dt
from CTE
-- where datepart(dw, dt) = 1
option (maxrecursion 1600);
select *, datePart(wk, [date]) as [standard_wk]
from #tblSundays
I don't see how you could have those two condition on that same snippet, but you could add a second query there to complete what you are trying to do.
Something like this, maybe:
SET datefirst 7
DECLARE #tblSundays TABLE
(
[year] INT,
[month] INT,
[week] INT,
[date] DATETIME
)
DECLARE #DateFrom DATETIME = '2020-12-12',
#DateTo DATETIME = '2021-06-06';
--select #DateFrom,#DateTo;
WITH cte (dt)
AS (SELECT #DateFrom
UNION ALL
SELECT Dateadd(d, 1, dt)
FROM cte
WHERE dt < #DateTo)
INSERT INTO #tblSundays
SELECT Datepart(year, dt),
Datepart(month, dt),
Datepart(week, dt),
dt
FROM cte
WHERE Datepart("dw", dt) = 1
OPTION (maxrecursion 1000);
--second new query
WITH cte (dt)
AS (SELECT #DateFrom
UNION ALL
SELECT Dateadd(d, 1, dt)
FROM cte
WHERE dt < #DateTo)
INSERT INTO #tblSundays
SELECT Datepart(year, dt),
Datepart(month, dt),
Datepart(week, dt),
dt
FROM cte
WHERE Datepart("dw", dt) <> 1
AND Datepart(day, dt) = 1
AND Datepart(week, dt) NOT IN (SELECT week
FROM #tblSundays)
OPTION (maxrecursion 1000);
SELECT *
FROM #tblSundays
ORDER BY year,
month,
week
Would that be OK?

How to fix the SELECT that use a virtual Table using Group by

I would like to get the count of EventType by month.
I've trying the next 2 possibility:
First possibility
DECLARE #StartDate date
SET #StartDate = GETDATE() - 365;
WITH theDates AS
(SELECT #StartDate as theDate
UNION ALL
SELECT DATEADD(MONTH, 1, theDate)
FROM theDates
WHERE DATEADD(MONTH, 1, theDate) <= GETDATE()
)
SELECT 'Diagnosis' as EventType,
MONTH(theDate),
YEAR(theDate),
concat(MONTH(theDate),'/', YEAR(theDate)),
Count(fpd.DateOfServiceID) as Eventcount
FROM theDates dd
LEFT JOIN fact.FactPatientDiagnosis fpd ON fpd.DateOfServiceID = concat(YEAR(theDate), MONTH(theDate), DAY(theDate))
GROUP BY YEAR(dd.theDate), MONTH(dd.theDate)
I've getting the value 0 for the EventCount Column
But i know that are in the table more than 500 Diagnosis
Second Possibility
DECLARE #StartDate date
SET #StartDate = GETDATE() - 365;
WITH theDates AS
(SELECT #StartDate as theDate
UNION ALL
SELECT DATEADD(MONTH, 1, theDate)
FROM theDates
WHERE DATEADD(MONTH, 1, theDate) <= GETDATE()
)
SELECT 'Diagnosis' as EventType,
MONTH(theDate),
YEAR(theDate),
concat(MONTH(theDate),'/', YEAR(theDate)),
Count(fpd.DateOfServiceID) as Eventcount
FROM theDates dd
LEFT JOIN fact.FactPatientDiagnosis fpd ON fpd.DateOfServiceID is not NULL
GROUP BY YEAR(dd.theDate), MONTH(dd.theDate)
In this Select, I've getting the value 503 for the EventCount column
I assume you want:
SET #StartDate = GETDATE() - 365;
WITH theDates AS (
SELECT #StartDate as theDate
UNION ALL
SELECT DATEADD(MONTH, 1, theDate)
FROM theDates
WHERE DATEADD(MONTH, 1, theDate) <= GETDATE()
)
SELECT 'Diagnosis' as EventType,
YEAR(theDate), MONTH(theDate),
concat(MONTH(theDate), '/', YEAR(theDate)),
Count(fpd.DateOfServiceID) as Eventcount
FROM theDates dd LEFT JOIN
fact.FactPatientDiagnosis fpd
ON fpd.DateOfServiceID >= dd.theDate AND
fpd.DateOfServiceID < DATEADD(month, 1, dd.theDate)
GROUP BY YEAR(dd.theDate), MONTH(dd.theDate)
ORDER BY YEAR(dd.theDate), MONTH(dd.theDate);
You are generating 1 date for each month in CTE (picking current DAY), and comparing it with dateofserviceid, even some date matches, every day you will get different output.
Ideally you should be comparing only YEAR and MONTH part for the JOIN.
LEFT JOIN fact.factpatientdiagnosis fpd ON
month(fpd.dateofserviceid) = month(thedate)
AND
year(fpd.dateofserviceid) = year(thedate)
Your overall query should look like following now.
DECLARE #StartDate DATE
SET #StartDate = Getdate() - 365;
WITH thedates
AS (SELECT #StartDate AS theDate
UNION ALL
SELECT Dateadd(month, 1, thedate)
FROM thedates
WHERE Dateadd(month, 1, thedate) <= Getdate())
SELECT 'Diagnosis' AS EventType,
Month(thedate),
Year(thedate),
Concat(Month(thedate), '/', Year(thedate)),
Count(fpd.dateofserviceid) AS Eventcount
FROM thedates dd
LEFT JOIN fact.factpatientdiagnosis fpd
ON Month(fpd.dateofserviceid) = Month(thedate)
AND Year(fpd.dateofserviceid) = Year(thedate)
GROUP BY Year(dd.thedate),
Month(dd.thedate)
Why would you ever want to use Int for a date IDK. I assume your DateOfServiceID is a date representation in int format like 20180102 (yyyyMMdd). If so:
WITH myData (theDate)
AS (SELECT CONVERT(DATE, CAST(DateOfServiceId AS VARCHAR(8)), 112)
FROM fact.FactPatientDiagnosis
WHERE DateOfServiceId >= CAST(CONVERT(VARCHAR(10), DATEADD(DAY, -365, CAST(GETDATE() AS DATE)), 112) AS INT))
SELECT 'Diagnosis' AS EventType,
MONTH(theDate) AS mn,
YEAR(theDate) AS yr,
SUBSTRING(CONVERT(VARCHAR(10), theDate, 103), 4, 7) AS MonthYear,
COUNT(theDate) AS Eventcount
FROM myData
GROUP BY MONTH(theDate),
YEAR(theDate),
SUBSTRING(CONVERT(VARCHAR(10), theDate, 103), 4, 7)
ORDER BY YEAR(theDate),
MONTH(theDate);

How to generate minute intervals between two dates in T-SQL?

I have a table of startTime and endTimes. I need to generate a table of intervals between those two dates in minutes. Here's some sample data:
declare #intervalMinutes int = 10
declare #myDates table (
myId int primary key identity,
startTime datetime,
endTime datetime
)
insert #myDates (startTime, EndTime) values ('2016-07-10 08:00','2016-07-10 09:00')
insert #myDates (startTime, EndTime) values ('2016-07-12 10:00','2016-07-12 12:00')
insert #myDates (startTime, EndTime) values ('2016-07-14 12:30','2016-07-14 14:30')
What I'd like to see is for each myId a set of dates of interval #intervalMinutes.
So if we had #intervalMinutes set to 10 then I'd see for the first row a list of 6 dates between 2016-07-10 08:00 and 2016-07-10 09:00 in 10 minute increments.
You can use recursive query like this :
declare #intervalMinutes int = 10
declare #myDates table (
myId int primary key identity,
startTime datetime,
endTime datetime
)
DECLARE #startTime DATETIME = '2016-07-10 08:00'
DECLARE #endTime DATETIME = '2016-07-10 09:00'
;WITH CTE AS
(
SELECT #startTime st
UNION ALL
SELECT dateadd(MINUTE,#intervalMinutes,st) st
FROM cte
where dateadd(MINUTE,#intervalMinutes,st) < #endTime
)
INSERT INTO #myDates(startTime,endTime)
SELECT st,dateadd(MINUTE,#intervalMinutes,st) FROM cte
SELECT * FROm #myDates
A numbers/tally table would do the trick as Gordon mentioned. However, I use a UDF to create dynamic date ranges.
For example
Select * from [dbo].[udf-Create-Range-Date]('2016-07-10 08:00','2016-07-10 09:00','MI',10)
Returns
RetVal
2016-07-10 08:00:00.000
2016-07-10 08:10:00.000
2016-07-10 08:20:00.000
2016-07-10 08:30:00.000
2016-07-10 08:40:00.000
2016-07-10 08:50:00.000
2016-07-10 09:00:00.000
The UDF
CREATE FUNCTION [dbo].[udf-Create-Range-Date] (#DateFrom datetime,#DateTo datetime,#DatePart varchar(10),#Incr int)
Returns
#ReturnVal Table (RetVal datetime)
As
Begin
With DateTable As (
Select DateFrom = #DateFrom
Union All
Select Case #DatePart
When 'YY' then DateAdd(YY, #Incr, df.dateFrom)
When 'QQ' then DateAdd(QQ, #Incr, df.dateFrom)
When 'MM' then DateAdd(MM, #Incr, df.dateFrom)
When 'WK' then DateAdd(WK, #Incr, df.dateFrom)
When 'DD' then DateAdd(DD, #Incr, df.dateFrom)
When 'HH' then DateAdd(HH, #Incr, df.dateFrom)
When 'MI' then DateAdd(MI, #Incr, df.dateFrom)
When 'SS' then DateAdd(SS, #Incr, df.dateFrom)
End
From DateTable DF
Where DF.DateFrom < #DateTo
)
Insert into #ReturnVal(RetVal) Select DateFrom From DateTable option (maxrecursion 32767)
Return
End
-- Syntax Select * from [dbo].[udf-Create-Range-Date]('2016-10-01','2020-10-01','YY',1)
-- Syntax Select * from [dbo].[udf-Create-Range-Date]('2016-10-01','2020-10-01','DD',1)
-- Syntax Select * from [dbo].[udf-Create-Range-Date]('2016-10-01','2016-10-31','MI',15)
-- Syntax Select * from [dbo].[udf-Create-Range-Date]('2016-10-01','2016-10-02','SS',1)
A numbers table can solve your problem. Assuming you don't need more than a few thousand rows, then this should work:
with n as (
select row_number() over (order by (select null)) - 1 as n
from master.spt_values
)
select d.*,
dateadd(minute, n.n * #intervalMinutes, d.startTime)
from #myDates d join
n
on dateadd(minute, n.n * #intervalMinutes, d.startTime) <= d.endTime;
To add to #GordonLinoff 's good answer, Jonathan Roberts (from SQLServerCentral.com - See the link in the revision history in the code for the original article) wrote a dandy function that'll handle pretty much anything. The flower box pretty much explains it all along with some example usage Here's his code from his article.
/**********************************************************************************************************************
FUNCTION: DateRange
Returns a table of datetime values based on the parameters
Parameters:
#StartDate :Start date of the series
#EndDate :End date of the series
#DatePart :The time unit for #interval
ns : nanoseconds
mcs : microseconds
ms : milliseconds
ss : seconds
mi : minutes
hh : hours
dd : days
ww : weeks
mm : months
qq : quarters
yy : years
#Interval :The number of dateparts between each value returned
Sample Calls:
SELECT * FROM [dbo].[DateRange]('2011-01-01 12:24:35', '2011-02-01 12:24:35', 'ss', 2);
SELECT COUNT(*) FROM [dbo].[DateRange]('2018-01-01 00:00:00', '2018-01-25 20:31:23.646', 'ms', default);
SELECT * FROM [dbo].[DateRange]('2011-01-01', '2012-02-03', default, default);
SELECT * FROM [dbo].[DateRange]('2012-02-03', '2011-01-01', 'dd', 7);
SELECT DATEDIFF(ns,'2018-01-01 00:00:00.000', value),Value,*
FROM [dbo].[DateRange]('2018-01-01 00:00:00.000', '2018-01-01 00:00:00.00001', 'ns', 100);
-----------------------------------------------------------------------------------------------------------------------
Revision History:
Rev 00 - 29 Aug 2019 - Jonathan Roberts
- Initial release
- Ref: https://www.sqlservercentral.com/scripts/a-daterange-table-valued-function
**********************************************************************************************************************/
CREATE FUNCTION [dbo].[DateRange]
(
#StartDate datetime2,
#EndDate datetime2,
#DatePart nvarchar(3)='dd',
#Interval int=1
)
RETURNS TABLE AS RETURN
WITH A(A) AS (SELECT 0 FROM (VALUES (0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) A(A)),
B(RowNum) AS (SELECT TOP(ABS(CASE #DatePart
WHEN 'ns' THEN DATEDIFF(ns, #EndDate, #StartDate)/#Interval
WHEN 'mcs' THEN DATEDIFF(mcs,#EndDate, #StartDate)/#Interval
WHEN 'ms' THEN DATEDIFF(ms, #EndDate, #StartDate)/#Interval
WHEN 'ss' THEN DATEDIFF(ss, #EndDate, #StartDate)/#Interval
WHEN 'mi' THEN DATEDIFF(mi, #EndDate, #StartDate)/#Interval
WHEN 'hh' THEN DATEDIFF(hh, #EndDate, #StartDate)/#Interval
WHEN 'dd' THEN DATEDIFF(dd, #EndDate, #StartDate)/#Interval
WHEN 'ww' THEN DATEDIFF(ww, #EndDate, #StartDate)/#Interval
WHEN 'mm' THEN DATEDIFF(mm, #EndDate, #StartDate)/#Interval
WHEN 'qq' THEN DATEDIFF(qq, #EndDate, #StartDate)/#Interval
WHEN 'yy' THEN DATEDIFF(yy, #EndDate, #StartDate)/#Interval
ELSE DATEDIFF(dd, IIF(#StartDate < #EndDate, #StartDate, #EndDate), IIF(#StartDate < #EndDate, #EndDate, #StartDate))/#Interval
END) + 1)
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1
FROM A A, A B, A C, A D, A E, A F, A G, A H) -- A maximum of 16^8 (or 2^32) rows could be returned from this inline tally
SELECT CASE #DatePart
WHEN 'ns' THEN DATEADD(ns, T.AddAmount, #StartDate)
WHEN 'mcs' THEN DATEADD(mcs,T.AddAmount, #StartDate)
WHEN 'ms' THEN DATEADD(ms, T.AddAmount, #StartDate)
WHEN 'ss' THEN DATEADD(ss, T.AddAmount, #StartDate)
WHEN 'mi' THEN DATEADD(mi, T.AddAmount, #StartDate)
WHEN 'hh' THEN DATEADD(hh, T.AddAmount, #StartDate)
WHEN 'dd' THEN DATEADD(dd, T.AddAmount, #StartDate)
WHEN 'ww' THEN DATEADD(ww, T.AddAmount, #StartDate)
WHEN 'mm' THEN DATEADD(mm, T.AddAmount, #StartDate)
WHEN 'qq' THEN DATEADD(qq, T.AddAmount, #StartDate)
WHEN 'yy' THEN DATEADD(yy, T.AddAmount, #StartDate)
ELSE DATEADD(dd, T.AddAmount, #StartDate)
END [Value]
FROM B
CROSS APPLY(VALUES (IIF(#StartDate<#EndDate, #interval*RowNum, #interval*-RowNum))) T(AddAmount)
GO

how to get the start and end dates of all weeks between two dates in SQL server?

I need to get all week start and end dates(weeks) between two dates and then run a query returning the number of records inserted in each of those weeks.
declare #sDate datetime,
#eDate datetime;
select #sDate = '2013-02-25',
#eDate = '2013-03-25';
--query to get all weeks between sDate and eDate
--query to return number of items inserted in each of the weeks returned
WEEK NoOfItems
-----------------------------------------
2013-02-25 5
2013-03-4 2
2013-03-11 7
You can use a recursive CTE to generate the list of dates:
;with cte as
(
select #sDate StartDate,
DATEADD(wk, DATEDIFF(wk, 0, #sDate), 6) EndDate
union all
select dateadd(ww, 1, StartDate),
dateadd(ww, 1, EndDate)
from cte
where dateadd(ww, 1, StartDate)<= #eDate
)
select *
from cte
See SQL Fiddle with Demo.
Then you can join this to your table, to return the additional details.
Here is my solution. Inspired by this answer
DECLARE #sDate DATE = DATEADD(MONTH, -6, GETDATE())
DECLARE #eDate DATE = GETDATE()
;WITH cte AS
(
SELECT DATEADD(WEEK, DATEDIFF(WEEK, 0, #sDate), 0) AS StartDate, DATEADD(WEEK, DATEDIFF(WEEK, 0, #sDate), 6) AS EndDate
UNION ALL
SELECT DATEADD(WEEK, 1, StartDate), DATEADD(WEEK, 1, EndDate)
FROM cte
WHERE DATEADD(WEEK, 1, StartDate) <= #eDate
)
SELECT * FROM cte

Resources