How to weekly aggregate data in sql and include skipped weeks too - sql

I am working in SQL Server 2008. I am writing a stored procedure which aggregates data on a weekly basis.
Code for aggregation is
ALTER PROCEDURE [dbo].[ups_URLBatchStats]
(#startDate datetime, #endDate datetime,#source varchar(8))
AS BEGIN
SELECT
DATEADD(wk, DATEDIFF(wk, 0, ScheduleDate), 6) AS [Week Commencing],
SUM(Unresolved) AS Unresolved,
SUM(Resolved) AS Resolved,
SUM(TurkSpend) AS TurkSpend
FROM
dbo.V_URLBatchStats
WHERE
ScheduleDate BETWEEN #startDate AND #endDate
AND Source = ISNULL(#source, Source)
GROUP BY
DATEADD(wk, DATEDIFF(wk, 0, ScheduleDate), 6)
ORDER BY
DATEADD(wk, DATEDIFF(wk, 0, ScheduleDate), 6)
END
Show it gives me correct result, but if there are no data for any week I have to show it with values of '0' in the columns.
So how can I handled these skipped weekly rows?
Thanks in advance.

It seems like you are currently selecting the wrong week, I tried to fix this:
SELECT dateadd(wk, number, DATEADD(wk, DATEDIFF(wk, 0, #startdate)-1, 6)) AS [Week Commencing],
coalesce(SUM(Unresolved), 0) AS Unresolved,
coalesce(sum(Resolved), 0)as Resolved,
coalesce(sum(TurkSpend), 0) as TurkSpend
FROM dbo.V_URLBatchStats
right join
master..spt_values
on ScheduleDate between #startDate and #endDate and Source=ISNULL(#source,Source)
where type = 'P' and dateadd(wk, number, DATEADD(wk, DATEDIFF(wk, 0, #startdate)-1, 6)) <= #enddate
GROUP BY dateadd(wk, number, DATEADD(wk, DATEDIFF(wk, 0, #startdate)-1, 6))
ORDER BY dateadd(wk, number, DATEADD(wk, DATEDIFF(wk, 0, #startdate)-1, 6))

You can RIGHT JOIN your week column with sysobjects with a row number generated:
SELECT o.Num AS [Week Commencing], SUM(Unresolved) AS Unresolved,sum(Resolved)as Resolved,sum(TurkSpend) as TurkSpend
FROM dbo.V_URLBatchStats s
RIGHT JOIN (SELECT ROW_NUMBER() OVER (ORDER BY object_id) as [Num] FROM sysobjects) o
on DATEADD(wk, DATEDIFF(wk, 0, ScheduleDate), 6) = o.Num
WHERE ScheduleDate between #startDate and #endDate
AND Source=ISNULL(#source,Source)
GROUP BY DATEADD(wk, DATEDIFF(wk, 0, ScheduleDate), 6), o.Num
ORDER BY 1
Note this is written from memory and untested, but the principle should work.

Related

Get every month of the current year in SQL Server

I'm using the following code to get the date of every day in the current week, in SQL Server:
SELECT
DATEADD(wk, DATEDIFF(wk, 0, GETDATE()), 0) Monday,
DATEADD(wk, DATEDIFF(wk, 0, GETDATE()), 0) + 1 Tuesday,
DATEADD(wk, DATEDIFF(wk, 0, GETDATE()), 0) + 2 Wednsday,
DATEADD(wk, DATEDIFF(wk, 0, GETDATE()), 0) + 3 Thursday,
DATEADD(wk, DATEDIFF(wk, 0, GETDATE()), 0) + 4 Friday,
DATEADD(wk, DATEDIFF(wk, 0, GETDATE()), 0) + 5 Saturday,
DATEADD(wk, DATEDIFF(wk, 0, GETDATE()), 0) + 6 Sunday;
I'm using this query to fill a bar chart in a asp.net application.
I need the same thing but with the months of the current year.
Can you help me with this, please?
Edit: More like a query to retrieve data from every month of this year.
This will return the first and last day of every month for the current year.
select FirstDay = dateadd(month, thisMonth - 1, dateadd(year, datediff(year, 0, getdate()), 0))
, LastDay = dateadd(day, -1, dateadd(month, thisMonth, dateadd(year, datediff(year, 0, getdate()), 0)))
from
(
values(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)
) x(thisMonth)

Week of the Month in SQL

DECLARE #date DATETIME= GETDATE()
SELECT DATEDIFF(WEEK,
DATEADD(WEEK,
DATEDIFF(WEEK, 0,
DATEADD(MONTH, DATEDIFF(MONTH, 0, #date), 0)),
0), #date - 1) + 1
What is purpose of 0 as a parameter in the datediff() function?
The specific answer to your question is that the 0 is just a way to get the beginning of the month:
dateadd(month, datediff(month, 0, #date), 0)
This is one method to do this in SQL Server, because it does not offer a "date truncate" function. I prefer:
dateadd(day, 1 - day(#date), #date)
(Although admittedly this is a wee bit more complicated if #date has a time component.)
However, a much simpler way to do this is:
select (day(#date) - 1) / 7) as week_of_month
Below gets the number of months from a reference point
datediff(month, 0, #date)
Then it is used to add to the reference date back to reach the first day of the month
dateadd(month,
datediff(month, 0, #date),
0)
So it is used to find the first day of the current month
declare #date datetime = getdate()
select
getdate(),
datediff(month, 0, #date),
dateadd(month,
datediff(month, 0, #date),
0)

SQL Last Three Months

I have wrote SQL to select user data for last three months, but I think at the moment it updates daily.
I want to change it so that as it is now October it will not count Octobers data but instead July's to September data and change to August to October when we move in to November
This is the SQL I got at the moment:
declare #Today datetime
declare #Category varchar(40)
set #Today = dbo.udf_DateOnly(GETDATE())
set #Category = 'Doctors active last three months updated'
declare #last3monthsnew datetime
set #last3monthsnew=dateadd(m,-3,dbo.udf_DateOnly(GETDATE()))
delete from LiveStatus_tbl where Category = #Category
select #Category, count(distinct U.userid)
from UserValidUKDoctor_vw U
WHERE LastLoggedIn >= #last3monthsnew
How would I edit this to do that?
WHERE LastLoggedIn >= DATEADD(month, DATEDIFF(month, 0, GETDATE())-3, 0)
AND LastLoggedIn < DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0)
The above statement will return any results in July till before the start of current month.
Referencing this answer to get the first day of the month:
How can I select the first day of a month in SQL?
You can detect the month limitations like so:
select DATEADD(month, DATEDIFF(month, 0, getdate()) - 3, 0) AS StartOfMonth
select DATEADD(month, DATEDIFF(month, 0, getdate()), 0) AS EndMonth
Then you can add that into variables or directly into your WHERE clause:
declare #StartDate datetime
declare #EndDate datetime
set #StartDate = DATEADD(month, DATEDIFF(month, 0, getdate()) - 3, 0)
set #EndDate = DATEADD(month, DATEDIFF(month, 0, getdate()), 0)
select #Category, count(distinct U.userid)
from UserValidUKDoctor_vw U
where LastLoggedIn >= #StartDate AND LastLoggedIn < #EndDate
Or:
select #Category, count(distinct U.userid)
from UserValidUKDoctor_vw U
where LastLoggedIn >= DATEADD(month, DATEDIFF(month, 0, getdate()) - 3, 0)
and LastLoggedIn < DATEADD(month, DATEDIFF(month, 0, getdate()), 0)
How about using BETWEEN ?
WHERE LastLoggedIn
BETWEEN
DATEADD(month, DATEDIFF(month, 0, GETDATE())-3, 0)
AND
DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0)

SQL - Get data based on months form a dateTime column

With SQL Server, I have a column with a launch date (dateTime). I want to report on everything that is being launched between all of last month (from viewing date) thru all of this month and next month.
So basically a full 3 month period.
What is the best way to write that?
Are you looking for something like this?
DECLARE
#StartDate DATETIME,
#EndDate DATETIME
SELECT
#StartDate = DATEADD(MM, DATEDIFF(MM, 0, GETDATE()) - 1, 0),
#EndDate = DATEADD(MM, DATEDIFF(MM, 0, GETDATE()) + 2, 0)
-- DATEADD(MM, DATEDIFF(MM, 0, GETDATE()), 0), -- beginning of this month
-- DATEADD(MM, DATEDIFF(MM, 0, GETDATE()) - 1, 0), -- beginning of last month
-- DATEADD(MM, DATEDIFF(MM, 0, GETDATE()) + 1, 0) -- beginning of next month
-- DATEADD(MM, DATEDIFF(MM, 0, GETDATE()) + 2, 0) -- beginning of two months from now
SELECT
*
FROM
[Table]
WHERE
[LaunchDate] >= #StartDate
AND [LaunchDate] < #EndDate
This will give you all the results starting from the beginning of the previous month and before the beginning of two months from now (a full 3 month range)
Maybe something like SELECT /*what_you_want*/ from launches WHERE lauchDate BETWEEN DATEADD(MONTH, DATEDIFF(MONTH, '19000101', GETDATE()) - 1, '19000101') AND DATEADD(MONTH, DATEDIFF(MONTH, '19000101', GETDATE()) + 2, '19000101')
SELECT Foo
FROM Bar
WHERE LaunchDate >= DATEADD(mm, -1, GETDATE())
AND LaunchDate <= DATEADD(mm, 1, GETDATE())

GETDATE last month

I am trying to list last a website's statistics.
I listed Last 30 days with;
CONVERT(VARCHAR(10), S.DATEENTERED, 101)
BETWEEN
CONVERT(VARCHAR(10), GETDATE()-30, 101)
AND
CONVERT(VARCHAR(10), GETDATE(), 101)
and this month with;
RIGHT(CONVERT(VARCHAR(10), S.DATEENTERED, 103), 7) =
RIGHT(CONVERT(VARCHAR(10), GETDATE(), 103), 7)
but I have no idea what query to use for last month. I tried with;
RIGHT(CONVERT(VARCHAR(10), S.DATEENTERED, 103), 7) =
RIGHT(CONVERT(VARCHAR(10), GETDATE()-1, 103), 7)
Did not work.
Dates are always a joy to work with in any programming language, SQL not excluded.
To answer your question to find all records that occurred last month
select S.DATEENTERED
,*
from sometable S
where S.DATEENTERED
between dateadd(mm, datediff(mm, 0, dateadd(MM, -1, getdate())), 0)
and dateadd(ms, -3, dateadd(mm, datediff(mm, 0, dateadd(MM, -1, getdate())) + 1, 0))
order by 1
To expand the best means for getting records within a certain time-frame is by utilizing the datediff function, dateadd function, and the between condition in the where clause.
select 'howdy'
,getdate()
where getdate()
between dateadd(mm, 0, 0)
and dateadd(ms, -3, dateadd(mm, datediff(mm, 0, dateadd(mm,-1,getutcdate())) + 1, 0))
The above code will result in no records returned because it is checking to see if today's date is between 1900-01-01 00:00:00.000 and the last possible recorded date of last month (the last day and 23:59:59.997 - SQL Server DATETIME columns have at most a 3 millisecond resolution).
The following code will return a record as the date we are searching for is one month ago.
select 'howdy'
,dateadd(mm, -1, getdate())
where dateadd(mm, -1, getdate())
between dateadd(mm, 0, 0)
and dateadd(ms, -3, dateadd(mm, datediff(mm, 0, dateadd(mm,-1,getutcdate())) + 1, 0))
A break down of the where clause:
WHERE getdate() -- date to check
between dateadd(mm, 0, 0) -- begin date
and dateadd(ms, -3, dateadd(mm, datediff(mm, 0, dateadd(mm,-1,getutcdate())) + 1, 0)) -- end date
Finally, a variety of dates can be ascertained in this manner here is a pretty complete list:
select dateadd(mm, 0, 0) as BeginningOfTime
,dateadd(dd, datediff(dd, 0, getdate()), 0) as Today
,dateadd(wk, datediff(wk, 0, getdate()), 0) as ThisWeekStart
,dateadd(mm, datediff(mm, 0, getdate()), 0) as ThisMonthStart
,dateadd(qq, datediff(qq, 0, getdate()), 0) as ThisQuarterStart
,dateadd(yy, datediff(yy, 0, getdate()), 0) as ThisYearStart
,dateadd(dd, datediff(dd, 0, getdate()) + 1, 0) as Tomorrow
,dateadd(wk, datediff(wk, 0, getdate()) + 1, 0) as NextWeekStart
,dateadd(mm, datediff(mm, 0, getdate()) + 1, 0) as NextMonthStart
,dateadd(qq, datediff(qq, 0, getdate()) + 1, 0) as NextQuarterStart
,dateadd(yy, datediff(yy, 0, getdate()) + 1, 0) as NextYearStart
,dateadd(ms, -3, dateadd(dd, datediff(dd, 0, getdate()) + 1, 0)) as TodayEnd
,dateadd(ms, -3, dateadd(wk, datediff(wk, 0, getdate()) + 1, 0)) as ThisWeekEnd
,dateadd(ms, -3, dateadd(mm, datediff(mm, 0, getdate()) + 1, 0)) as ThisMonthEnd
,dateadd(ms, -3, dateadd(qq, datediff(qq, 0, getdate()) + 1, 0)) as ThisQuarterEnd
,dateadd(ms, -3, dateadd(yy, datediff(yy, 0, getdate()) + 1, 0)) as ThisYearEnd
Using the above list a range of any type can be determined.
The following will find you the start of the last month:
-- Start of last month
SELECT CAST('01 '+ RIGHT(CONVERT(CHAR(11),DATEADD(MONTH,-1,GETDATE()),113),8) AS datetime)
You would then find the start of this month, using the following, minus one.
-- Start of the month
SELECT CAST('01 '+ RIGHT(CONVERT(CHAR(11),GETDATE(),113),8) AS datetime)
When I have to work with dates in SQL Server I often reference Robyn Page's SQL Server DATE/TIME Workbench. The workbench (tutorial) is well laid out and contains just about everything I have ever needed when working with dates on SQL Server.
How about this?
select DATEADD(month, -1, GETDATE())
I would suggest using the first day of last month and the first day of the current month for the operation and rather than using BETWEEN use >= and <. That's my personal opinion, but I believe you will find there are performance and maintainability benefits to this approach.
Here's the sql. You will notice I've included the last day of the last month value just in case you end up going with another approach.
Keep in mind, these dates are based off of 12:00AM that day. In other words, getting values between 6/1/2009 and 6/30/2009 won't get you what you want as all of 6/30/2009 is excluded. If you use the first day of July (7/1/2009) you are covered.
Again, I recommend avoiding BETWEEN all together as shown below. Best of luck.
Declare #LastMonthFirstDay datetime
Declare #LastMonthLastDay datetime
Declare #ThisMonthFirstDay datetime
Set #LastMonthFirstDay = DATEADD(MONTH, DATEDIFF(MONTH, 0, CURRENT_TIMESTAMP) - 1, 0);
Set #ThisMonthFirstDay = DATEADD(MONTH, DATEDIFF(MONTH, 0, CURRENT_TIMESTAMP), 0);
Set #LastMonthLastDay = DATEADD(DAY, -1, DATEADD(MONTH, DATEDIFF(MONTH, 0, CURRENT_TIMESTAMP), 0));
Select * From Table
Where DateEntered >= #LastMonthFirstDay
And DateEntered < #ThisMonthFirstDay;
Try using the DATEADD function. You can add a -1 with the MONTH (mm) datepart and it should work. Here is a link
where year(S.DATEENTERED) = year(dateadd(mm, -1, getdate())) and month(S.DATEENTERED) = month(dateadd(mm, -1, getdate()))
Might not be good performance-wise but you've got the idea.
GET FIRST DAY OF LAST MONTH
SELECT DATEADD(MM, DATEDIFF(MM, '01/01/2000', DATEADD(MM, -1,GETDATE())), '01/01/2000')
GET LAST DAY OF LAST MONTH
SELECT DATEADD(SS,-1,DATEADD(MM, DATEDIFF(MM,'01/01/2000',GETDATE()),'01/01/2000'))
Then search based on this range.
Try:
declare #lastm int
set #lastm = datepart(mm,getdate()) - 1
...
where datepart(mm,s.dateentered) = #lastm