Rounding of hours in sql queries - sql

The values ​​you see below are loaded with a query and they are related to a time stamp. What they ask me to insert is a rounded value; up and down. Rounding must be done at minutes of 15 and 30.
If the round is set to 15 and the marking has been made at 7:59, it is rounded off to 8:00 if the marking is at 8:01 am rounded to 8:15 am, as do I implement this thing within this query?
Query:
select Data, string_agg(Ore, ' ') as Ore
from (
select FORMAT(DataCreazione, 'dd/MM/yyyy', 'it-IT') as Data,
CONCAT(DATEPART(HOUR,DataCreazione), ':', DATEPART(MINUTE, DataCreazione)) as
Ore
from Marcatura
where IdUtente = 2
and (Stato='Ingresso' or Stato='Uscita')
and cast(DataCreazione as DateTime)
between cast(CONVERT(VARCHAR(10), CONVERT(date, '10-11-18', 5), 23) as datetime)
and cast(CONVERT(VARCHAR(10), CONVERT(date, '10-11-19', 5), 23) as datetime)
) t
group by Data
order by CONVERT(datetime, Data, 105) desc
Values:
05/07/2019 -- 14:45 19:27
04/07/2019 -- 11:41 11:41
07/06/2019 -- 12:39
01/06/2019 -- 8:27 8:27 8:27 8:27
18/04/2019 -- 15:41 15:41
08/04/2019 -- 11:52 11:54
01/04/2019 -- 7:25
27/03/2019 -- 21:38 21:38
23/03/2019 -- 13:32 13:32
08/03/2019 -- 21:20 21:20
04/03/2019 -- 21:48 21:48
02/03/2019 -- 8:3 8:3
If the state is equal to < Ingresso > it is rounded up to the top if the status is < Uscita > is rounded down, for example 07:59 becomes 08:00 whereas if it is 17:44 it becomes 17:45

I would use timefromparts():
select dateadd(minute,
(case when datepart(minute, #time) not in (0, 15, 30, 45) then 15 else 0 end),
timefromparts(datepart(hour, #time),
15 * floor(datepart(minute, #time) / 15.0) % 60,
0, 0, 0
)
)
This is a little more complicated because you want to round up. So the idea is to round down and then selectively add 15 minutes.

The Logic is much more simple than described, perhaps.
Try this approach:
EDIT: Applied logic to your own query
select Data, string_agg(Ore, ' ') as Ore
from (
select FORMAT(DataCreazione, 'dd/MM/yyyy', 'it-IT') as Data,
CONCAT(
(Case
when Datepart(MINUTE, DataCreazione) > 45
then Datepart(hour, Datacreazione)+1
else Datepart(hour, Datacreazione)
end)
,':'
,(case
when DATEPART(MINUTE, DataCreazione) between 0 and 15 then '15'
when DATEPART(MINUTE, DataCreazione) between 16 and 30 then '30'
when DATEPART(MINUTE, DataCreazione) between 31 and 45 then '45'
else '00' end
)) as Ore
from Marcatura
where IdUtente = 2
and (Stato='Ingresso' or Stato='Uscita')
and DataCreazione
between cast(CONVERT(VARCHAR(10), CONVERT(date, '10-11-18', 5), 23) as datetime)
and cast(CONVERT(VARCHAR(10), CONVERT(date, '10-11-19', 5), 23) as datetime)
) t
group by Data
order by CONVERT(datetime, Data, 105) desc;
SQLFiddle here:
http://sqlfiddle.com/#!18/475202/1
http://sqlfiddle.com/#!18/23d16/13

this logic might help.
declare #time time
set #time = '14:41'
select case
when datepart(mi, #time) between 15 and 30 then dateadd(mi, -datepart(mi, #time) + 30, #time)
when datepart(mi, #time) between 16 and 45 then dateadd(mi, -datepart(mi, #time) + 45, #time)
when datepart(mi, #time) between 46 and 59 then dateadd(mi, -datepart(mi, #time) + 60, #time)
else dateadd(mi, -datepart(mi, #time), #time) end
applying this in your query.
select Data, string_agg(Ore, ' ') as Ore
from (
select FORMAT(DataCreazione, 'dd/MM/yyyy', 'it-IT') as Data,
CONVERT(VARCHAR(5), (case
when datepart(mi, CONVERT(VARCHAR(5),DataCreazione,108)) between 15 and 30 then dateadd(mi, -datepart(mi, CONVERT(VARCHAR(5),DataCreazione,108))) + 30, CONVERT(VARCHAR(5),DataCreazione,108)))
when datepart(mi, CONVERT(VARCHAR(5),DataCreazione,108))) between 16 and 45 then dateadd(mi, -datepart(mi, CONVERT(VARCHAR(5),DataCreazione,108))) + 45, CONVERT(VARCHAR(5),DataCreazione,108)))
when datepart(mi, CONVERT(VARCHAR(5),DataCreazione,108))) between 46 and 59 then dateadd(mi, -datepart(mi, CONVERT(VARCHAR(5),DataCreazione,108))) + 60, CONVERT(VARCHAR(5),DataCreazione,108)))
else dateadd(mi, -datepart(mi, CONVERT(VARCHAR(5),DataCreazione,108))), CONVERT(VARCHAR(5),DataCreazione,108))) end), 108) as Ore
from Marcatura
where IdUtente = 2
and (Stato='Ingresso' or Stato='Uscita')
and cast(DataCreazione as DateTime)
between cast(CONVERT(VARCHAR(10), CONVERT(date, '10-11-18', 5), 23) as datetime)
and cast(CONVERT(VARCHAR(10), CONVERT(date, '10-11-19', 5), 23) as datetime)
) t
group by Data
order by CONVERT(datetime, Data, 105) desc

Related

How to calculate different between times in different hours?

I have the time-in and time-out of the employees. I can calculate the total hours out of it. The allow late mins are 30 per month. After crossing 30 mins threshold every minute will be calculated late.
The problem is that our office is divided into 4 times.
9:00 am to 11:00 am
11:15 am to 11:30 am (Break)
01:00 pm to 02:00 pm (Break)
02:00 pm to 05:00 pm
05:15 pm to 06:00 pm (Break)
Now if you come late after 09:00 am, it will be calculated late, if you come after 11:30 again late, same for 02:00 pm and 05:15 pm.
How would I calculate something like and wold contribute to late mins > 30.
For this I have 5 columns TimeIN, TimeOUT , TotalHours, AllowedLateMins adn employeeID.
SELECT DATEDIFF(MINUTE, TimeIN, , TimeOUT) AS TotalHours
But for the different breaks etc I can not calculate.
Update: For now I m doing this.
Select InTime, OutTime, DATEDIFF(Minute, InTime, OutTime) as Diff, Sum(DATEDIFF(Minute, InTime, OutTime))
Over(Order by e_id rows unbounded preceding) as Total
from [UNIS 22Dec].[dbo].[Tb_Compile_Attendance]
where e_id= 1001
Updte:
till now I hve done this.
Select top(1) TotalTimeTobeSpent from MinutesConfig
Declare #TimetoBeSpent int
Set #TimetoBeSpent = (Select top(1) TotalTimeTobeSpent from MinutesConfig)
Select top(1) TotalTimeTobeSpent from MinutesConfig
Declare #FlexiMins int
Set #FlexiMins = (Select top(1) FlexiMins from MinutesConfig)
Select InTime, OutTime, DATEDIFF(Minute, InTime, OutTime) as Diff,
SUM(DATEDIFF(Minute, InTime, OutTime)) Over() TotalHrs
from [UNIS 22Dec].[dbo].[Tb_Compile_Attendance]
Declare #RemFlxMins int
/****** Script for SelectTopNRows command from SSMS ******/
SELECT TOP 1000 [id] 'S.No'
,[e_date] 'Date'
,[e_id] 'Employee ID'
,[e_name] 'EmployeeName'
,[InTime]
,[OutTime]
,[Indate]
,[outdate],
DATEDIFF(Minute, Case when CAST(InTime AS time) < '08:30' then '08:30' else InTime end, Case when CAST(OutTime AS Time) > '18:00' then '18:00' when (CAST(OutTime AS Time) > '10:00' AND CAST(OutTime AS Time) < '10:15') then '10:00' else OutTime end) as 'Difference (Mins)',
#TimetoBeSpent 'TimeToBeSpent (Mins)',
SUM(DATEDIFF(Minute, Case when CAST(InTime AS time) < '08:30' then '08:30' else InTime end, Case when CAST(OutTime AS Time) > '18:00' then '18:00' when (CAST(OutTime AS Time) > '10:00' AND CAST(OutTime AS Time) < '10:15') then '10:00' else OutTime end)) Over() 'ActualTimeSpent (Mins)',
(#TimetoBeSpent - SUM(DATEDIFF(Minute, Case when CAST(InTime AS time) < '08:30' then '08:30' else InTime end,Case when CAST(OutTime AS Time) > '18:00' then '18:00' when (CAST(OutTime AS Time) > '10:00' AND CAST(OutTime AS Time) < '10:15') then '10:00' else OutTime end)) Over()) 'Late (Mins)',
(#FlexiMins - (#TimetoBeSpent - SUM(DATEDIFF(Minute, Case when CAST(InTime AS time) < '08:30' then '08:30' else InTime end,Case when CAST(OutTime AS Time) > '18:00' then '18:00' when (CAST(OutTime AS Time) > '10:00' AND CAST(OutTime AS Time) < '10:15') then '10:00' else OutTime end)) Over())) 'RemainingFlexiMins',
#FlexiMins as AllowedFlexiMins
FROM [Tb_Compile_Attendance]
where InTime is not null and outtime is not null
Output:
S.No Date Employee ID InTime OutTime Indate outdate Difference (Mins) TimeToBeSpent (Mins) ActualTimeSpent (Mins) Late (Mins) RemainingFlexiMins AllowedFlexiMins
145 20190721 1001 08:30 10:01 20190721 20190721 90 480 476 4 86 90
164 20190721 1001 10:16 13:00 20190721 20190721 164 480 476 4 86 90
165 20190721 1001 14:03 16:15 20190721 20190721 132 480 476 4 86 90
166 20190721 1001 16:30 18:01 20190721 20190721 90 480 476 4 86 90
I created a table with work periods (the periods when a worker MUST be at work, without breaks). Here's my version of periods, change these data as you need:
create table dbo.WorkTimePeriods
(
FromTime time not null,
TillTime time not null,
constraint pk_dbo_worktimeperiods primary key (FromTime, TillTime),
)
go
insert dbo.WorkTimePeriods
(FromTime,TillTime)
values (cast('09:00:00 am' as time),cast('11:00:00 am' as time)),
(cast('11:30:00 am' as time),cast('01:00:00 pm' as time)),
(cast('02:00:00 pm' as time),cast('06:00:00 pm' as time))
So, the resulting query looks like this (with my sample data for Employees visiting):
;with cte as
(
select *
from (
values (1, cast('20190101 08:59:00' as datetime), cast('20190101 11:00:53' as datetime)), -- this guy is normal one
(1, cast('20190101 11:29:50' as datetime), cast('20190101 13:05:00' as datetime)),
(1, cast('20190101 13:58:31' as datetime), cast('20190101 18:05:10' as datetime)),
(2, cast('20190101 08:59:00' as datetime), cast('20190101 18:00:53' as datetime)), -- this guy works without breaks - workaholic!
(3, cast('20190101 09:09:11' as datetime), cast('20190101 12:59:20' as datetime)), -- this guy was late and went after the afternoon - lazy one!
(4, cast('20190101 09:00:55' as datetime), cast('20190101 11:02:30' as datetime)), -- this guy is a normal one as well, but he is a bit late sometimes
(4, cast('20190101 11:28:22' as datetime), cast('20190101 13:05:10' as datetime)),
(4, cast('20190101 13:55:09' as datetime), cast('20190101 18:01:12' as datetime))
) as EmplWT (EmployeeId, InTime, OutTime)
),
cte2 as
(
select cast('20190101' as date) as CalendarDate
)
select v1.EmployeeId,
v1.CalendarDate,
sum(v1.PastDueTimeInSec/60.0) as PastDueTimeInMin,
sum((v1.WorkTimeInSec-v1.PastDueTimeInSec) / 60.0) as WorkTimeInMin
from (
select v3.EmployeeId,
t2.CalendarDate,
case when v4.EmployeeId is not null then 0
when v5.EmployeeId is null then datediff(SECOND, cast(t1.FromTime as datetime), cast(t1.TillTime as datetime))
else
case when v5.InTime > cast(t1.FromTime as datetime) + cast(t2.CalendarDate as datetime) then datediff(SECOND, cast(t1.FromTime as datetime) + cast(t2.CalendarDate as datetime), v5.InTime) else 0 end +
case when v5.OutTime < cast(t1.TillTime as datetime) + cast(t2.CalendarDate as datetime) then datediff(SECOND, v5.InTime, cast(t1.TillTime as datetime) + cast(t2.CalendarDate as datetime)) else 0 end
end as PastDueTimeInSec,
datediff(SECOND,cast(t1.FromTime as datetime), cast(t1.TillTime as datetime)) as WorkTimeInSec
from dbo.WorkTimePeriods t1
cross join cte2 t2
cross join (
select EmployeeId
from cte
group by EmployeeId
) v3
left join (
select t1.EmployeeId,
t1.InTime,
t1.OutTime
from cte t1
) v4 on cast(t1.FromTime as datetime) + cast(t2.CalendarDate as datetime) between v4.InTime and v4.OutTime
and cast(t1.TillTime as datetime) + cast(t2.CalendarDate as datetime) between v4.InTime and v4.OutTime
and v4.EmployeeId = v3.EmployeeId
left join (
select t1.EmployeeId,
t1.InTime,
t1.OutTime
from cte t1
) v5 on v5.InTime between cast(t1.FromTime as datetime) + cast(t2.CalendarDate as datetime) and cast(t1.TillTime as datetime) + cast(t2.CalendarDate as datetime)
and v5.EmployeeId = v3.EmployeeId
) v1
group by v1.EmployeeId,
v1.CalendarDate
Pay attention, you need to create a Calendar with work dates (in my case it's CTE2).
Result:
+------------+--------------+------------------+---------------+
| EmployeeId | CalendarDate | PastDueTimeInMin | WorkTimeInMin |
+------------+--------------+------------------+---------------+
| 1 | 01.01.2019 | 0.000000 | 450.000000 |
| 2 | 01.01.2019 | 0.000000 | 450.000000 |
| 3 | 01.01.2019 | 339.183333 | 110.816666 |
| 4 | 01.01.2019 | 0.916666 | 449.083333 |
+------------+--------------+------------------+---------------+
I hope this will help you. Good luck!:)

Grouping incident counts into 5 minute time segments

Hoping someone can assist with how to modify the following SQL to achieve the result shown in desired output. I am not fluent in TSQL but know enough to get this far.
My objectrive is to count my incident data and group into 15 minutes time segments starting at midnight but also include zero (0) where there is no incident data in a particular time segment.
Curent Query#
;With cte As
(SELECT CONVERT (varchar(5),DATEADD(minute, 15 *
(DATEDIFF(minute, '20000101', I.CreateTimestamp) / 15), '20000101'),108)
AS CreationTime, I.IncidentShortReference AS Ref
FROM Incident I
WHERE i.CreateTimestamp between DATEADD(d,-1,GETDATE()) and GETDATE()
)
SELECT CTE.CreationTime, count(CTE.Ref) As Count
FROM cte CTE
GROUP BY CTE.CreationTime
ORDER BY CTE.CreationTime
My result
CreationTime count
00:15 2
01:00 1
01:15 1
01:30 1
01:45 2
02:00 1
02:15 1
02:30 4
(Truncated)
Desired Output
CreationTime count
00:15 2
00:30 0
00:45 0
01:00 1
01:15 1
01:30 1
01:45 2
02:00 1
02:15 1
02:30 4
02:45 0
03:00 0
(Truncated)
This uses a cte creating a record for every timestamp between midnight yesterday and now, with a count for the number of incidents in each range with sample data:
declare #incident table (CreateTimestamp datetime, IncidentShortReference varchar(5))
insert into #incident values ('4/10/2017 11:11:00', 'test')
insert into #incident values ('4/10/2017 11:12:00', 'test')
insert into #incident values ('4/10/2017 11:21:00', 'test')
insert into #incident values ('4/10/2017 11:31:00', 'test')
insert into #incident values ('4/10/2017 13:31:00', 'test')
DECLARE #dt datetime
SELECT #dt = dateadd(d, datediff(d, 0, getdate()), 0) - 1 -- yesterday at midnight
;with cte as
(
select #dt dt
union all
select DATEADD(minute, 15, dt) as Next15
FROM cte
WHERE DATEADD(minute, 15, dt) < GETDATE()
)
select convert(varchar(5), dt, 108) as CreationTime, (select count(*) FROM #incident WHERE CreateTimestamp >= dt and CreateTimestamp < dateadd(mi, 15, dt)) as count
from cte
Sample output from a random interval:
You could create a time interval CTE table like this
WITH TIME_CTE
AS(
SELECT
CAST('20170411 00:15:00' AS DATETIME) AS TimePeriod
UNION ALL
SELECT
DATEADD(MINUTE, 15, TimePeriod)
FROM TIME_CTE
WHERE
DATEADD(MINUTE, 15, TimePeriod) < CAST('20170411 23:59:00' AS DATETIME)
)
SELECT
LEFT(CONVERT(VARCHAR(10),TimePeriod,108), 5)
FROM TIME_CTE
Then join it with your original query
WITH TIME_CTE
AS(
SELECT
CAST('20170411 00:15:00' AS DATETIME) AS TimePeriod
UNION ALL
SELECT
DATEADD(MINUTE, 15, TimePeriod)
FROM TIME_CTE
WHERE
DATEADD(MINUTE, 15, TimePeriod) < CAST('20170411 23:59:00' AS DATETIME)
),
CTE
AS (
SELECT CONVERT (varchar(5),DATEADD(minute, 15 *
(DATEDIFF(minute, '20000101', I.CreateTimestamp) / 15), '20000101'),108)
AS CreationTime, I.IncidentShortReference AS Ref
FROM Incident I
WHERE i.CreateTimestamp between DATEADD(d,-1,GETDATE()) and GETDATE()
)
SELECT TIME_CTE.TimePeriod, SUM(IIF(CTE.Ref IS NULL, 0, 1)) As Count
FROM TIME_CTE
LEFT JOIN CTE ON CTE.CreationTime = TIME_CTE.TimePeriod
GROUP BY TIME_CTE.TimePeriod
ORDER BY TIME_CTE.TimePeriod

Filtering data from the previous day using DateTime values

I am trying to retrieve data for yesterday's shift using SQL Server 2008 r2.
The shift starts at 20:00 pm, and ends 10:00 am following day.
What date function can I use to retrieve data for the entire shift?
Using this:
CAST([LastStartedDate] as time)> cast('20:00' as Time)
Will only retrieve data up to midnight.
You can filter your dates with a WHERE clause that uses some date manipulation like so:
WHERE LastStartedDate >= DATEADD(HOUR, 20,
CAST(CAST(DATEADD(DAY, -1, GETDATE()) AS DATE) AS DATETIME));
This first gets yesterdays date, as a DATE so it removes the time portion:
SELECT CAST(DATEADD(DAY, -1, GETDATE()) AS DATE)
-- 2017-03-06
Then converts it back to a DATETIME to add the time as midnight of that day:
SELECT CAST(CAST(DATEADD(DAY, -1, GETDATE()) AS DATE) AS DATETIME)
-- 2017-03-06 00:00:00.000
Then it adds 20 hours to get you to 20:00 - 8.00PM:
SELECT DATEADD(HOUR, 20,CAST(CAST(DATEADD(DAY, -1, GETDATE()) AS DATE) AS DATETIME));
-- 2017-03-06 20:00:00.000
For your scenario, you need to do the same again to get the 10am cut off too and use BETWEEN.
Example:
CREATE TABLE #shift
(
LastStartedDate DATETIME ,
WorkItemsDone INT
);
INSERT INTO #shift
( LastStartedDate, WorkItemsDone )
VALUES ( DATEADD(HOUR, -18, GETDATE()), 10 ),
( DATEADD(HOUR, -15, GETDATE()), 20 ),
( DATEADD(HOUR, -14, GETDATE()), 30 ),
( DATEADD(HOUR, -10, GETDATE()), 40 ),
( DATEADD(HOUR, -5, GETDATE()), 25 ),
( DATEADD(HOUR, -2, GETDATE()), 15 ),
( DATEADD(HOUR, 4, GETDATE()), 5 ),
( DATEADD(HOUR, 10, GETDATE()), 15 );
-- all data
SELECT *
FROM #shift
-- limited data
SELECT *
FROM #shift
WHERE LastStartedDate BETWEEN
DATEADD(HOUR, 20, CAST(CAST(DATEADD(DAY, -1, GETDATE()) AS DATE) AS DATETIME))
AND DATEADD(HOUR, 10, CAST(CAST(GETDATE() AS DATE) AS DATETIME))
DROP TABLE #shift;
Produces:
-- all data
LastStartedDate WorkItemsDone
2017-03-06 16:18:04.877 10
2017-03-06 19:18:04.877 20
2017-03-06 20:18:04.877 30
2017-03-07 00:18:04.877 40
2017-03-07 05:18:04.877 25
2017-03-07 08:18:04.877 15
2017-03-07 14:18:04.877 5
2017-03-07 20:18:04.877 15
-- filtered data
LastStartedDate WorkItemsDone
2017-03-06 20:18:04.877 30
2017-03-07 00:18:04.877 40
2017-03-07 05:18:04.877 25
2017-03-07 08:18:04.877 15

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)

find records from previous x days?

How can I come up with a stored procedure that selects results for past 30 days?
where MONTH(RequestDate) > 6 and DAY(RequestDate) >= 10
and MONTH(RequestDate) < 21 and DAY(RequestDate) < 7
SELECT *
FROM Table
WHERE GETDATE() >= DATEADD(DAY, -30, GETDATE())
Substitute the first GETDATE() with the appropriate column name.
SELECT *
FROM Table
WHERE Table.ColumnName >= DATEADD(DAY, -30, GETDATE())
Are you looking for last 30 days or last month? To find start and end of each month ("generic" as your comment says), use:
select dateadd(month,datediff(month,0,getdate()),0),
dateadd(mm,datediff(mm,-1,getdate()),-1)
Something like this?
CREATE PROC GetSomeHistory
#NumDaysPrevious int
AS
BEGIN
SELECT * FROM MyTable
WHERE RequestDate BETWEEN DATEADD(dd, -1 * #NumDaysPrevious, getdate())
AND getdate();
END
......
EXEC GetSomeHistory 55;
SELECT *
FROM Table
WHERE myDate >= DATEADD(MONTH, -1, GETDATE())
doing it by month is different than doing it in 30-day blocks. Test this out as follows...
declare #mydate smalldatetime
set #mydate = '07/6/01'
select #mydate
select DATEADD(month, 2, #mydate), DATEDIFF(day, DATEADD(month, 2, #mydate), #mydate)
select DATEADD(month, 1, #mydate), DATEDIFF(day, DATEADD(month, 1, #mydate), #mydate)
select DATEADD(month, -1, #mydate), DATEDIFF(day, DATEADD(month, -1, #mydate), #mydate)
select DATEADD(month, -2, #mydate), DATEDIFF(day, DATEADD(month, -2, #mydate), #mydate)
select DATEADD(month, -3, #mydate), DATEDIFF(day, DATEADD(month, -3, #mydate), #mydate)
Here are the results:
2001-07-06 00:00:00
2001-09-06 00:00:00 | -62
2001-08-06 00:00:00 | -31
2001-06-06 00:00:00 | 30
2001-06-06 00:00:00 | 30
2001-05-06 00:00:00 | 61
2001-04-06 00:00:00 | 91