?
Solved

Adding time conditions to query - help!

Posted on 2007-03-23
14
Medium Priority
?
222 Views
Last Modified: 2012-08-14
Dear Experts,

This query is proving to be a real problem - this is my third question so far! Please bear with me - I am learning from your answers.

I am trying to filter the following query down to all responses received within the last month (i.e. from 1st of the month to the current date).

I tried adding this onto the end of my query but it's skewing up my results set... It's meant to be grouped by username but is messing up when I add this in...

AND cbr.Date BETWEEN DATEADD(mm, DATEDIFF(mm, 0, GETDATE()), 0) AND GETDATE()

Entire query so far...
=======================
SELECT TOP (10) Username, Name, Person_ID, Company_ID, NoCompleted, NoAllocated, NoCompleted * 100 / NoAllocated AS OutputFigure
FROM (SELECT TOP (10) cb.Username, SUM(CASE WHEN cbr.call_id IS NULL THEN 0 ELSE 1 END) AS NoCompleted, COUNT(*) AS NoAllocated, People.Person_nameFirst + ' ' + People.Person_nameLast AS Name, People.Person_ID, ClientAccounts.Company_ID  
FROM CallBank AS cb
INNER JOIN  UserList ON cb.Username = UserList.User_Username
INNER JOIN  People ON UserList.Person_ID = People.Person_ID
INNER JOIN  ActivityOutlets ON cb.ActivityOutlet_ID = ActivityOutlets.ActivityOutlet_ID
INNER JOIN OutletList ON ActivityOutlets.Outlet_ID = OutletList.Outlet_ID
INNER JOIN AccountOutlets ON OutletList.Outlet_ID = AccountOutlets.Outlet_ID
INNER JOIN ClientAccounts ON AccountOutlets.Account_ID = ClientAccounts.Account_ID
LEFT OUTER JOIN CallBankResponse AS cbr ON cbr.Call_ID = cb.Call_ID
GROUP BY cb.Username, People.Person_nameFirst, People.Person_nameLast, People.Person_ID, ClientAccounts.Company_ID  
HAVING(ClientAccounts.Company_ID = 31)
ORDER BY NoAllocated DESC) AS derivedtbl_1
ORDER BY OutputFigure DESC
0
Comment
Question by:nkewney
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 4
  • 3
  • +1
14 Comments
 
LVL 10

Expert Comment

by:lahousden
ID: 18780505
Your BETWEEN condition is in error, since 0 is not a date (I am guessing that SQL is reporting a syntax error).  If you want just current month an easier condition to use would be:

AND YEAR(cbr.Date) = YEAR(GetDate()) and MONTH(cbr.Date) = MONTH(GetDate())
0
 
LVL 10

Expert Comment

by:lahousden
ID: 18780553
Apologies for short-changing you - my suggestion will be a poor performer on large populations.  A more efficient condition to use is:

AND cbr.Date >= convert (datetime, substring (convert (varchar, getdate(), 121), 1, 8) + '01', 121)
0
 
LVL 1

Author Comment

by:nkewney
ID: 18780561
hello lahousden,

Can you give me an example of how i would integrate it as I'm getting a Group By error?

Nick
0
The Eight Noble Truths of Backup and Recovery

How can IT departments tackle the challenges of a Big Data world? This white paper provides a roadmap to success and helps companies ensure that all their data is safe and secure, no matter if it resides on-premise with physical or virtual machines or in the cloud.

 
LVL 50

Expert Comment

by:Lowfatspread
ID: 18780571
add the condition to the left outer join on clause

SELECT Username
, People.Person_nameFirst + ' ' + People.Person_nameLast AS Name, Person_ID
, 31 as Company_ID
, NoCompleted
, NoAllocated
, (NoCompleted * 100.000) / NoAllocated AS OutputFigure
FROM (SELECT TOP 10 cb.Username, SUM(CASE WHEN cbr.call_id IS NULL THEN 0 ELSE 1 END) AS NoCompleted
, COUNT(*) AS NoAllocated, , UserList.Person_ID  
FROM CallBank AS cb
INNER JOIN  UserList
ON cb.Username = UserList.User_Username
INNER JOIN  ActivityOutlets
ON cb.ActivityOutlet_ID = ActivityOutlets.ActivityOutlet_ID
INNER JOIN OutletList
ON ActivityOutlets.Outlet_ID = OutletList.Outlet_ID
INNER JOIN AccountOutlets
ON OutletList.Outlet_ID = AccountOutlets.Outlet_ID
INNER JOIN ClientAccounts
 ON AccountOutlets.Account_ID = ClientAccounts.Account_ID
LEFT OUTER JOIN CallBankResponse AS cbr
ON cbr.Call_ID = cb.Call_ID
and cbr.Date BETWEEN convert(datetime,Convert(char(8),DATEADD(d,((-1)*Day(getdate()) + 1),Getdate()),112)) AND GETDATE()
Where ClientAccounts.Company_ID = 31
GROUP BY cb.Username, Userlist.Person_ID
ORDER BY NoAllocated DESC
) AS x
INNER JOIN  People
ON x.Person_ID = People.Person_ID
ORDER BY OutputFigure DESC
 
 
i've also moved the person table join to the outer query... for efficiency (you shouldn't need it on the inside)

also you having condition is actually a where condition... (just use having for aggregate comparisions..)

and the company id  is known so you shouldn't need it in the actual query results...
(so if you must just add it as a literal into the outer select)

the top 10 isn't required on the outer query you'll only get 10 anyway...

hth
0
 
LVL 50

Expert Comment

by:Lowfatspread
ID: 18780595
yes sorry like lahousden's method of getting day 1 better...

and cbr.Date BETWEEN convert(datetime,Convert(char(6),getdate(),112)+'01') AND GETDATE()

but do use char(6) and avoid the substring...
0
 
LVL 10

Expert Comment

by:lahousden
ID: 18780912
(Don't know what is up with my "internal QA" today) - and, of course, my last post assumes that there are no rows where the value of cbr.date is greater than right now...
0
 
LVL 1

Author Comment

by:nkewney
ID: 18780955
Perfect, lowfatspread - really appreciate your help here.

Can you tell me how I could apply the same to 'week' and 'year' ?

Don't quite follow the logic behind the date part!!

Thanks

Nick
0
 
LVL 1

Author Comment

by:nkewney
ID: 18781090
Sorry just to clarify, i mean:

Week, Find the first day of the current week (assuming it starts Monday at 12:01am)
Year, Find the first day of the current year in the same foramt.

Thanks

Nick
0
 
LVL 50

Expert Comment

by:Lowfatspread
ID: 18781694
year is easy

and cbr.Date BETWEEN convert(datetime,Convert(char(4),getdate(),112)+'0101') AND GETDATE()

Week is more trouble...

assuming you haven't altered datefirst...
so that Sunday=1, Monday=2,..
then
and cbr.Date BETWEEN convert(datetime,Convert(char(6),getdate(),112)+Right('0' + convert(varchar(2),day(dateadd(d,Case Datepart(dw,Getdate()) when 1 then 0 when 0 then -6 else 1 - datepart(dw,getdate()) end,getdate())))  ) AND GETDATE()


basically
Convert(char(6),getdate(),112)

style 112 is YYYYMMDD  so the convert extracts year + month asa desired...

the rest of it  

datepart(dw,getdate())  returns the day of the week ... 0 is sunday, 1 is monday
so the case works out an adjustment for the dateadd to calulate the previous monday..
ie 6 days ago if sunday
    1 - dw if tues ... etc  



when you don't sepecify a time you get the start of the day...

hth
0
 
LVL 1

Author Comment

by:nkewney
ID: 18782069
Lowfatspread,

I think I am beginning to get this. Seems quite daunting at first though..

The week one returns the following...

System.Data.SqlClient.SqlException: The right function requires 2 argument(s).

Also, last thing I'll ask of you... how would I approach 'today' only (not within last 24 hours..) just today!

Thanks again for this.

Nick
0
 
LVL 19

Expert Comment

by:folderol
ID: 18784219
With all points to lowfatspread, I was listening to the Maple Leafs game and playing with this and I came up with these mods...  there are two queries here, try the top to see how the if statements work, then paste the query on the bottom into QA to create a procedure...

Tom
-- ===============================
-- this starts the test.  copy / paste these lines to query analyzer to see how it works...

declare @today datetime, @startdate datetime, @test varchar(20)
-- change the next two lines to test program flow
set @today = '20070320 12:00'      -- adjust to see outcome for different calendar days
set @test = 'day'                  --

if @test = 'day'
begin
select @startdate = cast(datediff(day, 0, @today) as datetime)
end
if @test = 'week'
begin
select @startdate =
cast(floor(cast(@today as float)) - datepart(weekday,@today) + case datepart(weekday,@today) when 1 then - 5 else 2 end as datetime)
end
if @test = 'month'
begin
select @startdate = convert(datetime,Convert(char(6),getdate(),112)+'01')
end
if @test = 'year'
begin
select @startdate = convert(datetime,Convert(char(4),getdate(),112)+'0101')
end

select @startdate

-- end of test

--=======================================
-- This starts the stored procedure.  copy / paste these lines into a new query window.
--drop procedure COMPANY_31_RPT
create procedure COMPANY_31_RPT @rpt_type varchar(20) = 'month' as

declare @startdate datetime

if @rpt_type = 'day'
begin
select @startdate = cast(datediff(day, 0, getdate()) as datetime)
end
if @rpt_type = 'week'
begin
select @startdate =
cast(floor(cast(getdate() as float)) - datepart(weekday,getdate()) + case datepart(weekday,getdate()) when 1 then - 5 else 2 end as datetime)
end
if @rpt_type = 'month'
begin
select @startdate = convert(datetime,Convert(char(6),getdate(),112)+'01')
end
if @rpt_type = 'year'
begin
select @startdate = convert(datetime,Convert(char(4),getdate(),112)+'0101')
end

if @rpt_type in ('day', 'week', 'month', 'year')
begin


SELECT Username
, People.Person_nameFirst + ' ' + People.Person_nameLast AS Name, Person_ID
, 31 as Company_ID
, NoCompleted
, NoAllocated
, (NoCompleted * 100.000) / NoAllocated AS OutputFigure
FROM (SELECT TOP 10 cb.Username, SUM(CASE WHEN cbr.call_id IS NULL THEN 0 ELSE 1 END) AS NoCompleted
, COUNT(*) AS NoAllocated, , UserList.Person_ID  
FROM CallBank AS cb
INNER JOIN  UserList
ON cb.Username = UserList.User_Username
INNER JOIN  ActivityOutlets
ON cb.ActivityOutlet_ID = ActivityOutlets.ActivityOutlet_ID
INNER JOIN OutletList
ON ActivityOutlets.Outlet_ID = OutletList.Outlet_ID
INNER JOIN AccountOutlets
ON OutletList.Outlet_ID = AccountOutlets.Outlet_ID
INNER JOIN ClientAccounts
 ON AccountOutlets.Account_ID = ClientAccounts.Account_ID
LEFT OUTER JOIN CallBankResponse AS cbr
ON cbr.Call_ID = cb.Call_ID
and cbr.Date BETWEEN @startdate and GETDATE()
Where ClientAccounts.Company_ID = 31
GROUP BY cb.Username, Userlist.Person_ID
ORDER BY NoAllocated DESC
) AS x
INNER JOIN  People
ON x.Person_ID = People.Person_ID
ORDER BY OutputFigure DESC

end


-- end procedure

-- sample procedure call statement.  time period is optional, if omitted, month report version runs.
COMPANY_31_RPT [year]
0
 
LVL 50

Accepted Solution

by:
Lowfatspread earned 2000 total points
ID: 18784569
sorry

right...

and cbr.Date BETWEEN convert(datetime,Convert(char(6),getdate(),112)+Right('0' + convert(varchar(2),day(dateadd(d,Case Datepart(dw,Getdate()) when 1 then 0 when 0 then -6 else 1 - datepart(dw,getdate()) end,getdate())),2)  ) AND GETDATE()

today

between convert(datetime,convert(char(8),getdate(),112)) and getdate()

or
between convert(datetime,convert(char(8),getdate(),112))
        and convert(datetime,convert(char(8),getdate(),112) + ' 23:59:59.997')

(.997 since datetime only as a precision of .003 )
 
0
 
LVL 1

Author Comment

by:nkewney
ID: 18791944
Lowfatspread - you have been a fantastic help!

The week line still returns the following...

The right function requires 2 argument(s).

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Data.SqlClient.SqlException: The right function requires 2 argument(s).

Source Error:


Line 60:
Line 61:
Line 62:         dbAdapter.Fill(ds)
Line 63:


0
 
LVL 1

Author Comment

by:nkewney
ID: 18808084
Absolutely fantastic.

Thanks lowfatspread - it worked perfectly.

Nick
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Microsoft Access is a place to store data within tables and represent this stored data using multiple database objects such as in form of macros, forms, reports, etc. After a MS Access database is created there is need to improve the performance and…
In this series, we will discuss common questions received as a database Solutions Engineer at Percona. In this role, we speak with a wide array of MySQL and MongoDB users responsible for both extremely large and complex environments to smaller singl…
Via a live example, show how to backup a database, simulate a failure backup the tail of the database transaction log and perform the restore.
Via a live example, show how to setup several different housekeeping processes for a SQL Server.
Suggested Courses

764 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question