Find out the number of Days and nights using sql query - sql

I would like to find out the number of days and nights in a given date range in sql. Can anyone help me? Thanks in advance.

Try something like this:
declare #t table(datefrom datetime, dateto datetime)
insert #t values('2012-01-01 11:30', '2012-01-01 12:30')
insert #t values('2012-01-01 11:30', '2012-01-02 00:30')
insert #t values('2012-01-01 12:30', '2012-01-02 13:00')
insert #t values('2012-01-01 12:30', '2012-01-02 00:30')
insert #t values('2012-01-01 00:00', '2012-01-03 00:00')
select datefrom, dateto,
datediff(day, datefrom - .5,dateadd(minute, -1, dateto)) nights,
datediff(day, datefrom, dateadd(minute, -1, dateto)+.5) days
from #t t
Result:
datefrom dateto nights days
2012-01-01 11:30 2012-01-01 12:30 1 1
2012-01-01 11:30 2012-01-02 00:30 2 1
2012-01-01 12:30 2012-01-02 13:00 1 2
2012-01-01 12:30 2012-01-02 00:30 1 1
2012-01-01 00:00 2012-01-03 00:00 2 2

See the AnandPhadke's comment, and here is the code :)
DECLARE #StartDate DATETIME = '2012-01-01'
DECLARE #EndDate DATETIME = '2012-02-01'
SELECT DATEDIFF(DAY, #StartDate, #EndDate) AS [Days], DATEDIFF(DAY, #StartDate, #EndDate) AS [Nights ]

Have you tried Datediff
Nights
select DATEDIFF (d, getdate()-1,getdate())
Days
select DATEDIFF (d, getdate()-1,getdate()) - 1

Related

Get every 2 weeks on particular days SQL Server

I have a query getting the days in particular day that I selected and show the days in a month. My problem is that I need every two weeks of the month. And I also need to get long date format: dddd, dd MMMM yyyy and eliminate the time. Please help me.
DECLARE #startDate DATETIME = '9/1/2019'
DECLARE #endDate DATETIME = '12/31/2019'
DECLARE #dayOfWeek INT = 1;
WITH cte_Recursion AS
(
SELECT #startDate AS [Date]
UNION ALL
SELECT DATEADD(DAY, 1, [Date])
FROM cte_Recursion
WHERE [Date] < #endDate
)
SELECT [Date]
FROM cte_Recursion
WHERE DATEPART(WEEKDAY, [Date]) = #dayOfWeek
OPTION (MAXRECURSION 0)
The data returned looks like this:
2019-09-01 00:00:00.000
2019-09-08 00:00:00.000
2019-09-15 00:00:00.000
2019-09-22 00:00:00.000
2019-09-29 00:00:00.000
2019-10-06 00:00:00.000
2019-10-13 00:00:00.000
2019-10-20 00:00:00.000
2019-10-27 00:00:00.000
2019-11-03 00:00:00.000
2019-11-10 00:00:00.000
2019-11-17 00:00:00.000
2019-11-24 00:00:00.000
And I need to get like this (every other week):
2019-09-01 00:00:00.000
2019-09-15 00:00:00.000
2019-09-29 00:00:00.000
2019-10-13 00:00:00.000
2019-10-27 00:00:00.000
2019-11-10 00:00:00.000
2019-11-24 00:00:00.000
By changing your CTE to start on the correct day of the week, you can then change the recursion to add 14 days instead of 1, giving you the desired result without further manipulation:
DECLARE #startDate DATETIME = '9/1/2019'
DECLARE #endDate DATETIME = '12/31/2019'
DECLARE #dayOfWeek INT = 1;
WITH cte_Recursion AS
(SELECT DATEADD(DAY, ((#dayOfWeek - DATEPART(WEEKDAY, #startDate)) % 7 + 7) %7, #startDate) AS [Date]
UNION ALL SELECT DATEADD(DAY, 14, [Date])
FROM cte_Recursion
WHERE DATEADD(DAY, 14, [Date]) < #endDate)
SELECT [Date] FROM cte_Recursion
Output:
Date
01/09/2019 00:00:00
15/09/2019 00:00:00
29/09/2019 00:00:00
13/10/2019 00:00:00
27/10/2019 00:00:00
10/11/2019 00:00:00
24/11/2019 00:00:00
08/12/2019 00:00:00
22/12/2019 00:00:00
Demo on dbfiddle
To change the date format to dddd, dd MMMM yyyy, simply replace the final SELECT with:
SELECT FORMAT([Date], 'dddd, dd MMMM yyyy') AS [Date] FROM cte_Recursion
Output:
Date
Sunday, 01 September 2019
Sunday, 15 September 2019
Sunday, 29 September 2019
Sunday, 13 October 2019
Sunday, 27 October 2019
Sunday, 10 November 2019
Sunday, 24 November 2019
Sunday, 08 December 2019
Sunday, 22 December 2019
Demo on dbfiddle
you can use it :
DECLARE #startDate DATETIME = '9/1/2019'
DECLARE #endDate DATETIME = '12/31/2019'
DECLARE #dayOfWeek INT = 1;
WITH cte_Recursion AS
(
SELECT #startDate AS [Date]
UNION ALL SELECT DATEADD(DAY, 1, [Date])
FROM cte_Recursion WHERE [Date] < #endDate
)
SELECT [Date] FROM cte_Recursion
WHERE DATEPART(WEEKDAY, [Date]) = #dayOfWeek
and DATEPART(WEEK, [Date]) % 2 = 0
OPTION (MAXRECURSION 0)
You could use a recursive CTE as
WITH CTE AS
(
SELECT '2019-09-01 00:00:00.000' ADate
UNION SELECT '2019-09-08 00:00:00.000'
UNION SELECT '2019-09-15 00:00:00.000'
UNION SELECT '2019-09-22 00:00:00.000'
UNION SELECT '2019-09-29 00:00:00.000'
UNION SELECT '2019-10-06 00:00:00.000'
UNION SELECT '2019-10-13 00:00:00.000'
UNION SELECT '2019-10-20 00:00:00.000'
UNION SELECT '2019-10-27 00:00:00.000'
UNION SELECT '2019-11-03 00:00:00.000'
UNION SELECT '2019-11-10 00:00:00.000'
UNION SELECT '2019-11-17 00:00:00.000'
UNION SELECT '2019-11-24 00:00:00.000'
),
F AS
(
SELECT CAST('2019-09-01 00:00:00.000' AS DATETIME) ADate
UNION ALL
SELECT DATEADD(Day, 14, F.ADate)
FROM F
WHERE ADate < '2019-11-24 00:00:00.000'
)
SELECT *
FROM F;

SQL Query for midnight transactions

What query do I use to get transactions including midnight (past midnight). For instance:
On 1st January 2018
Our Department Stores opens daily from 7am until 2am(next day)
So 2am transactions as seen as the sale for '1 January 2018'
This is my Query
WHERE Date BETWEEN '2018-01-01' AND '2018-01-02'
and Time >= '1754-01-01 07:00:00.000' and Time <='1754-01-01 01:59:00.000'
Currently my query only takes transactions until 11:59:59
But our store opens past midnight,
I want to get transaction everyday until 2am
Ideally you should combine the Date and Time column inside a single DATETIME column. Having said that, the following should work:
WITH testdata(Date, Time) AS (
SELECT '2018-01-01', '1754-01-01 06:00:00' UNION
SELECT '2018-01-01', '1754-01-01 07:00:00' UNION
SELECT '2018-01-01', '1754-01-01 08:00:00' UNION
SELECT '2018-01-01', '1754-01-01 23:00:00' UNION
SELECT '2018-01-02', '1754-01-01 00:00:00' UNION
SELECT '2018-01-02', '1754-01-01 01:00:00' UNION
SELECT '2018-01-02', '1754-01-01 06:00:00' UNION
SELECT '2018-01-02', '1754-01-01 07:00:00' UNION
SELECT '2018-01-02', '1754-01-01 08:00:00' UNION
SELECT CAST(NULL AS DATE), CAST(NULL AS DATETIME) -- type cast
)
SELECT *
FROM testdata
WHERE Date BETWEEN '2018-01-01' AND '2018-01-02'
AND (
Date = '2018-01-01' AND Time >= '1754-01-01 07:00:00' OR
Date = '2018-01-02' AND Time < '1754-01-01 07:00:00'
)
For completeness, I am including any transaction before 7:00 AM to previous day. Result:
| Date | Time |
|------------|-------------------------|
| 2018-01-01 | 1754-01-01 07:00:00.000 |
| 2018-01-01 | 1754-01-01 08:00:00.000 |
| 2018-01-01 | 1754-01-01 23:00:00.000 |
| 2018-01-02 | 1754-01-01 00:00:00.000 |
| 2018-01-02 | 1754-01-01 01:00:00.000 |
| 2018-01-02 | 1754-01-01 06:00:00.000 |
if date column has time then just use
WHERE Date>='2018-01-01 07:00:00.000' AND Date<='2018-01-02 01:59:00.000'
As your day is offset by 2 hours into the following day, I would just pull your date back by 2 hours.
Here is some example / test code. The select subtracts 2 hours from the input #testdate datetime and then truncates it to the day, chopping off the hours
declare #testdate as datetime = '2018-01-01 10:15'
select cast(dateadd(hour,-2,#testdate) as date)
set #testdate = '2018-01-02 01:15'
select cast(dateadd(hour,-2,#testdate) as date)
Both select statements return
2018-01-01
If you store date and time separately additionally run the following sql to combine them
cast(Date as datetime) + cast(Time as datetime)
e.g
select cast(dateadd(hour,-2,cast(Date as datetime) + cast(Time as datetime)) as date)
If you just want to get transactions for the given day, you could declare the date in a variable and then have the query search for records that are between (#date + 7 hours: 7 am) and (#date + 26 hours: 2 am the next day), which you can do by using the dateadd function. For simplicity, I've declared the startdate and enddate in variables as well.
Declare #date datetime = '2018-01-01';
Declare #startdate datetime = dateadd(hour, 7, #date);
Declare #enddate datetime = dateadd(hour, 26, #date);
select *
from table
WHERE Date BETWEEN #startdate AND #enddate
This will only work if your date column is of datetime datatype, though.
If you're storing your date and time in separate columns, you can combine them. Like so:
Declare #date datetime = '2018-01-01';
Declare #startdate datetime = dateadd(hour, 7, #date);
Declare #enddate datetime = dateadd(hour, 26, #date);
select *
from table
WHERE (cast(date as datetime) + cast(cast(time as time) as datetime))
BETWEEN #startdate AND #enddate

Need to add specific time to CTE_Dates calendar

I have a Dates CTE that allows me to fill in the dates between date stamped records. (Thanks SO!) However, I need the CTE_Dates table to time stamp its "StatusDate" column with a specific time instead of '00:00:00.000' and am not quite sure how to go about ding so. Here is the CTE_Dates code:
DECLARE #StartDate date = '07/15/2017'
DECLARE #EndDate date = '07/30/2017'
;WITH cte_Dates AS
(
SELECT
CASE WHEN DATEPART(DAY, #StartDate) = 1 THEN #StartDate ELSE DATEADD(Day, DATEDIFF(Day, 1, #StartDate) + 1, 0) END AS StatusDate
UNION ALL
SELECT DATEADD(Day, 1,StatusDate)
FROM cte_Dates
WHERE DATEADD(Day, 1, StatusDate) <= #EndDate
)
--this select statement actually pulls data from 2 CTE's that are joined but represents how I am pulling the StatusDate from CTE_Dates
select
CASE WHEN CAST(statusDate as Date) IS NULL
THEN LAG(cast(StatusDate as Date)) OVER (PARTITION BY item_no ORDER BY statStart)
ELSE StatusDate END as StatusDate,
SELECT * from cte_dates
Results:
StatusDate
2017-07-15 00:00:00.000
2017-07-16 00:00:00.000
2017-07-17 00:00:00.000
2017-07-18 00:00:00.000
2017-07-19 00:00:00.000
2017-07-20 00:00:00.000
2017-07-21 00:00:00.000
2017-07-22 00:00:00.000
2017-07-23 00:00:00.000
2017-07-24 00:00:00.000
2017-07-25 00:00:00.000
2017-07-26 00:00:00.000
2017-07-27 00:00:00.000
2017-07-28 00:00:00.000
2017-07-29 00:00:00.000
2017-07-30 00:00:00.000
The CTE works great! Except I need the timestamp to be noon...
Just add time value to date like this.
DECLARE #StartDate date = '07/15/2017'
DECLARE #EndDate date = '07/30/2017'
;WITH cte_Dates AS
(
SELECT
CASE WHEN DATEPART(DAY, #StartDate) = 1 THEN #StartDate ELSE DATEADD(Day, DATEDIFF(Day, 1, #StartDate) + 1, 0) END
+ '12:00'
AS StatusDate
UNION ALL
SELECT DATEADD(Day, 1,StatusDate)
FROM cte_Dates
WHERE DATEADD(Day, 1, StatusDate) <= #EndDate
)
SELECT * FROM CTE_Dates
You could use dateadd, adding 12 hours:
SELECT DATEADD(HOUR, 12, StatusDate) AS StatusDate FROM CTE_Dates
I would just use two CTEs:
DECLARE #StartDate date = '2017-07-15';
DECLARE #EndDate date = '2017-07-30';
DECLARE #time time = '04:00:00';
WITH cte_Dates AS (
SELECT CASE WHEN DATEPART(DAY, #StartDate) = 1 THEN #StartDate ELSE DATEADD(Day, DATEDIFF(Day, 1, #StartDate) + 1, 0) END AS StatusDate
UNION ALL
SELECT DATEADD(Day, 1,StatusDate)
FROM cte_Dates
WHERE DATEADD(Day, 1, StatusDate) <= #EndDate
),
cte_DateTimes as (
select cast(statusDate as datetime) + cast(#time as datetime)
from cte_Dates
)
SELECT *
FROM CTE_DateTimes;

Move Date to Monday in TSQL

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

displaying reporting weeks

I dont know how to loop through so that the query displays all the weeks from the reporting date?
The code determines the Mon - Sun week then should insert the values in a temp table to then query the weeks. I have hard coded the report_date and its hould display more than one record.
any ideas
DECLARE #REPORT_DATE DATETIME, #WEEK_BEGINING VARCHAR(10)
SELECT #REPORT_DATE = '2011-01-01T00:00:00'
--SELECT #REPORT_DATE = GETDATE() -- should grab the date now.
SELECT #WEEK_BEGINING = 'MONDAY'
IF #WEEK_BEGINING = 'MONDAY'
SET DATEFIRST 1
ELSE IF #WEEK_BEGINING = 'TUESDAY'
SET DATEFIRST 2
ELSE IF #WEEK_BEGINING = 'WEDNESDAY'
SET DATEFIRST 3
ELSE IF #WEEK_BEGINING = 'THURSDAY'
SET DATEFIRST 4
ELSE IF #WEEK_BEGINING = 'FRIDAY'
SET DATEFIRST 5
ELSE IF #WEEK_BEGINING = 'SATURDAY'
SET DATEFIRST 6
ELSE IF #WEEK_BEGINING = 'SUNDAY'
SET DATEFIRST 7
DECLARE #WEEK_START_DATE DATETIME, #WEEK_END_DATE DATETIME
--GET THE WEEK START DATE
SELECT #WEEK_START_DATE = #REPORT_DATE - (DATEPART(DW, #REPORT_DATE) - 1)
--GET THE WEEK END DATE
SELECT #WEEK_END_DATE = #REPORT_DATE + (7 - DATEPART(DW, #REPORT_DATE))
PRINT 'Week Start: ' + CONVERT(VARCHAR, #WEEK_START_DATE)
PRINT 'Week End: ' + CONVERT(VARCHAR, #WEEK_END_DATE)
CREATE TABLE #WeekList
(
month_date date
)
DECLARE #Interval int = 1
INSERT INTO #WeekList SELECT #WEEK_START_DATE
WHILE #Interval < 1
BEGIN
INSERT INTO #WeekList SELECT DATEADD(MONTH, - #Interval, #WEEK_START_DATE)
SET #Interval = #Interval + 1
END
SELECT
--Create the month ID code:
#WEEK_START_DATE AS Start_Week, #WEEK_END_DATE AS End_Week
FROM #WeekList
ORDER BY Start_Week DESC
DROP TABLE #WeekList
Using DATEADD and updating your #interval initialization and updated loop logic:
DECLARE #REPORT_DATE DATETIME, #WEEK_BEGINING VARCHAR(10)
SELECT #REPORT_DATE = '2011-01-01T00:00:00'
--SELECT #REPORT_DATE = GETDATE() -- should grab the date now.
SELECT #WEEK_BEGINING = 'MONDAY'
IF #WEEK_BEGINING = 'MONDAY'
SET DATEFIRST 1
ELSE IF #WEEK_BEGINING = 'TUESDAY'
SET DATEFIRST 2
ELSE IF #WEEK_BEGINING = 'WEDNESDAY'
SET DATEFIRST 3
ELSE IF #WEEK_BEGINING = 'THURSDAY'
SET DATEFIRST 4
ELSE IF #WEEK_BEGINING = 'FRIDAY'
SET DATEFIRST 5
ELSE IF #WEEK_BEGINING = 'SATURDAY'
SET DATEFIRST 6
ELSE IF #WEEK_BEGINING = 'SUNDAY'
SET DATEFIRST 7
DECLARE #WEEK_START_DATE DATETIME, #WEEK_END_DATE DATETIME
--GET THE WEEK START DATE
SELECT #WEEK_START_DATE = #REPORT_DATE - (DATEPART(DW, #REPORT_DATE) - 1)
--GET THE WEEK END DATE
SELECT #WEEK_END_DATE = #REPORT_DATE + (7 - DATEPART(DW, #REPORT_DATE))
PRINT 'Week Start: ' + CONVERT(VARCHAR, #WEEK_START_DATE)
PRINT 'Week End: ' + CONVERT(VARCHAR, #WEEK_END_DATE)
DECLARE #Interval int = datediff(WEEK,getdate(),#WEEK_START_DATE)+1
SELECT Start_Week=#WEEK_START_DATE
, End_Week=#WEEK_END_DATE
INTO #WeekList
WHILE #Interval <= 0
BEGIN
set #WEEK_START_DATE=DATEADD(WEEK,1,#WEEK_START_DATE)
set #WEEK_END_DATE=DATEADD(WEEK,1,#WEEK_END_DATE)
INSERT INTO #WeekList values (#WEEK_START_DATE,#WEEK_END_DATE)
SET #Interval += 1;
END
SELECT *
FROM #WeekList
ORDER BY Start_Week DESC
DROP TABLE #WeekList
Results (top 5 and bottom 5 of list):
Start_Week End_Week
----------------------- -----------------------
2012-03-12 00:00:00.000 2012-03-18 00:00:00.000
2012-03-05 00:00:00.000 2012-03-11 00:00:00.000
2012-02-27 00:00:00.000 2012-03-04 00:00:00.000
2012-02-20 00:00:00.000 2012-02-26 00:00:00.000
2012-02-13 00:00:00.000 2012-02-19 00:00:00.000
...
2011-01-24 00:00:00.000 2011-01-30 00:00:00.000
2011-01-17 00:00:00.000 2011-01-23 00:00:00.000
2011-01-10 00:00:00.000 2011-01-16 00:00:00.000
2011-01-03 00:00:00.000 2011-01-09 00:00:00.000
2010-12-27 00:00:00.000 2011-01-02 00:00:00.000
As an aside, you could also use the date type instead of Datetime, if you don't need to store the time.
If you would like to list the weeks and the corresponding counts or sums, you can do this as follows
Sample data
myDate
----------
2012-03-15
2012-03-15
2012-03-15
2012-03-14
2012-03-14
2012-03-14
2012-03-14
2012-03-09
2012-03-09
2012-03-09
2012-03-08
2012-03-08
2012-03-08
2012-03-01
2012-03-01
2012-03-01
2012-03-01
2012-02-29
2012-02-29
2012-02-29
2012-02-29
2012-02-23
2012-02-23
2012-02-23
2012-02-22
2012-02-22
2012-02-22
2012-02-22
Script for sample data
create table #myTable(mydate Date)
insert into #myTable select DATEADD(day, -1, getdate())
insert into #myTable select DATEADD(day, -1, getdate())
insert into #myTable select DATEADD(day, -1, getdate())
insert into #myTable select DATEADD(day, -2, getdate())
insert into #myTable select DATEADD(day, -2, getdate())
insert into #myTable select DATEADD(day, -2, getdate())
insert into #myTable select DATEADD(day, -2, getdate())
insert into #myTable select DATEADD(day, -7, getdate())
insert into #myTable select DATEADD(day, -7, getdate())
insert into #myTable select DATEADD(day, -7, getdate())
insert into #myTable select DATEADD(day, -8, getdate())
insert into #myTable select DATEADD(day, -8, getdate())
insert into #myTable select DATEADD(day, -8, getdate())
insert into #myTable select DATEADD(day, -15, getdate())
insert into #myTable select DATEADD(day, -15, getdate())
insert into #myTable select DATEADD(day, -15, getdate())
insert into #myTable select DATEADD(day, -15, getdate())
insert into #myTable select DATEADD(day, -16, getdate())
insert into #myTable select DATEADD(day, -16, getdate())
insert into #myTable select DATEADD(day, -16, getdate())
insert into #myTable select DATEADD(day, -16, getdate())
insert into #myTable select DATEADD(day, -22, getdate())
insert into #myTable select DATEADD(day, -22, getdate())
insert into #myTable select DATEADD(day, -22, getdate())
insert into #myTable select DATEADD(day, -23, getdate())
insert into #myTable select DATEADD(day, -23, getdate())
insert into #myTable select DATEADD(day, -23, getdate())
insert into #myTable select DATEADD(day, -23, getdate())
Expected Result
Count WeekStart WeekEnd
----- ---------- ----------
7 2012-02-20 2012-02-24
8 2012-02-27 2012-03-02
6 2012-03-05 2012-03-09
7 2012-03-12 2012-03-16
How to do
SET DATEFIRST 1
SELECT
COUNT(*) [Count],
DATEADD(DD, -(DATEPART(DW, mydate)-1), mydate) [WeekStart],
DATEADD(DD, 7-(DATEPART(DW, mydate)+2), mydate) [WeekEnd]
FROM
#myTable
WHERE
DATEPART(dw, mydate) >= 1 AND DATEPART(dw, mydate) <= 5 -- only weekdays
GROUP BY
DATEADD(DD, -(DATEPART(DW, mydate)-1), mydate),
DATEADD(DD, 7-(DATEPART(DW, mydate)+2), mydate)
ORDER BY
DATEADD(DD, -(DATEPART(DW, mydate)-1), mydate)