October 16, 2015 at 2:51 pm
Need help on writing case statement
We were assigned to modify the existing query. So, we need to write a Case Statement for two fields.
------------
1. We have a parameter called @StartDate (dateTime)
2. When the user type in a date, it will generate the days back for seven (7) days, EXCLUDING today's date. For example, if the user types in the date - for example ( Saturday - October 10, 2015), the query will generate seven days back, starting October 9 (Friday) and back to October 4, 2015 (Sunday).
3. Each row will contain the time (30 minutes interval), dayofWeek and the date (see photo below)
----------------------------
What we need to do: -- Look at photo attached.
1. Fill the OriginalDate field with the date that match the DayofWeek. For example, DayofWeek = 2, then, row # 1 for this field should be "2015-10-05 00:00:00.000". The parameter @Startdate will guide it.
DayofWeek = 3 (Tuesday); 4 = Wednesday, 5 = Thursday and 6 = Friday
2. Fill the Row_date with the OriginalDate + StartTime (converted). So, Row # 1 should display:
"2015-10-05 06:30:00.000" and row # 5 in Row_date column should display: "2015-10-05 08:30:00.000"
(I think I can figure out of how to do this part. It is a tricky one on converting substring. But, the main part is to get the main date first.)
--------------
Is it possible to fill this information using the CASE statement?
Thanks.
October 16, 2015 at 6:12 pm
You don't need a CASE statement for this. Post the code you used to generate the dates/times and we'll show you.
--Jeff Moden
Change is inevitable... Change for the better is not.
October 21, 2015 at 10:18 am
Thank you very much for your reply and I do apologize for the delays in my response.
The query itself combined three subqueries.
We would like to compare the number of last week (last 7 days), three months and six months based on particular day. For example, Wednesday of last week will be comparing with the average Wednesday for three and for six months.
I also create a screen shot for your review.
----------------------------
1. The user will enter a parameter date (any date)
2. The query will go back for seven days. For example, 10/10/2015, which was Saturday was entered. The query will go back seven days, Friday 10/9/2015 and back to 10/03/2015. Day of week will be displayed of what day it was.
3. Each day, we will have 30 minutes interval, see the "starttime" field.
--------------------------------
When running this query, I receive an empty (NULL) value in the date field.
For example,
Row 1, should be displayed as: '2015-10-05 06:30:00.000' based on the date + starttime of 0630
Row 5, should be displayed as: '2015-10-05 08:30:00.000' based on the date + starttime of 0830
-----------------------------------
I think, I can manipulate to find the way to display the time. However, I have the problem of how to put the date that correspond to the 'Day of Week' into the query without using the CASE statement.
The query is as follow:
--Declare @StartDate as Datetime
--Set @StartDate = '2015-10-10'
--(The @startdate can be any date but it will go back seven days.)
Select c.Row_date, e.DayofWeek, e.STARTTIME,
CASE WHEN c.TotalCallsOffered IS NULL THEN 0 ELSE c.TotalCallsOffered END as TotalCallsOffered
d.TotalCallsOfferedThreeMonths, e.TOTALCALLSOFFEREDSIXMONTHS
from
--Six Months Number
(
SELECT b.DAYOFWEEK, SUBSTRING(b.STARTTIME,1,2) + Substring(b.StartTime,4,2) as STARTTIME, SUM(b.CALLSOFFERED) OVER (PARTITION BY b.DAYOFWEEK, b.STARTTIME) AS TOTALCALLSOFFEREDSIXMONTHS
FROM (SELECT a.DayofWeek, a.StartTime, SUM(a.AnsweredCalls + a.AbandonCalls) AS CallsOffered
FROM (SELECT DATEADD(DAY, DATEDIFF(Day, 0, cqe.opened_at), 0) AS Row_Date, DATEPART(dw, cqe.opened_at) AS DayofWeek, CONVERT(char(5),
DATEADD(minute, CASE WHEN (datepart(minute, cqe.opened_at)) BETWEEN 0 AND 29 THEN 0 WHEN (datepart(minute, opened_at))
BETWEEN 30 AND 59 THEN 30 END, DATEADD(minute, - DATEPART(minute, cqe.opened_at), cqe.opened_at)), 108) AS StartTime,
AnsweredCalls,
AbandonCalls
FROM chat_queue_entry cqe INNER JOIN
chat_message cm ON cqe.chat_channel = cm.chat_channel
WHERE (cqe.opened_at >= @StartDate-181) AND (cqe.opened_at < DATEADD(Day, 1, @StartDate))
GROUP BY cqe.number, cqe.dv_action, cqe.opened_at) a
GROUP BY a.DayofWeek, a.StartTime) b
GROUP BY b.DayOfWeek, b.StartTime, b.CallsOffered
)e
LEFT JOIN
--Three Months Number
(
SELECT b.DAYOFWEEK, SUBSTRING(b.STARTTIME,1,2) + Substring(b.StartTime,4,2) as STARTTIME, SUM(b.CALLSOFFERED) OVER (PARTITION BY b.DAYOFWEEK, b.STARTTIME) AS TOTALCALLSOFFEREDTHREEMONTHS
FROM (SELECT a.DayofWeek, a.StartTime, SUM(a.AnsweredCalls + a.AbandonCalls) AS CallsOffered
FROM (SELECT DATEADD(DAY, DATEDIFF(Day, 0, cqe.opened_at), 0) AS Row_Date, DATEPART(dw, cqe.opened_at) AS DayofWeek, CONVERT(char(5),
DATEADD(minute, CASE WHEN (datepart(minute, cqe.opened_at)) BETWEEN 0 AND 29 THEN 0 WHEN (datepart(minute, opened_at))
BETWEEN 30 AND 59 THEN 30 END, DATEADD(minute, - DATEPART(minute, cqe.opened_at), cqe.opened_at)), 108) AS StartTime,
AnsweredCalls,
AbandonCalls
FROM chat_queue_entry cqe INNER JOIN
chat_message cm ON cqe.chat_channel = cm.chat_channel
WHERE (cqe.opened_at >= @StartDate-90) AND (cqe.opened_at < DATEADD(Day, 1, @StartDate))
GROUP BY cqe.dv_action, cqe.opened_at) a
GROUP BY a.DayofWeek, a.StartTime) b
GROUP BY b.DayOfWeek, b.StartTime, b.CallsOffered
)d
ON e.DayofWeek = d.DayofWeek and e.StartTime = d.STARTTIME
LEFT JOIN
--Last Week Number
(
SELECT b.ROW_DATE, b.OriginalDate, b.DAYOFWEEK, SUBSTRING(b.STARTTIME,1,2) + Substring(b.StartTime,4,2) as STARTTIME, SUM(b.CALLSOFFERED) OVER (PARTITION BY b.DAYOFWEEK, b.STARTTIME) AS TotalCallsOffered
FROM (SELECT a.Row_Date + a.StartTime AS Row_date, a.Row_Date as OriginalDate, a.DayofWeek, a.StartTime, SUM(a.AnsweredCalls + a.AbandonCalls)
AS CallsOffered
FROM (SELECT DATEADD(DAY, DATEDIFF(Day, 0, cqe.opened_at), 0) AS Row_Date, DATEPART(dw, cqe.opened_at) AS DayofWeek, CONVERT(char(5),
DATEADD(minute, CASE WHEN (datepart(minute, cqe.opened_at)) BETWEEN 0 AND 29 THEN 0 WHEN (datepart(minute, opened_at))
BETWEEN 30 AND 59 THEN 30 END, DATEADD(minute, - DATEPART(minute, cqe.opened_at), cqe.opened_at)), 108) AS StartTime,
AnsweredCalls,
AbandonCalls
FROM chat_queue_entry cqe INNER JOIN
chat_message cm ON cqe.chat_channel = cm.chat_channel
WHERE (cqe.opened_at >= @StartDate-6) AND (cqe.opened_at < DATEADD(Day, 1, @StartDate))
GROUP BY cqe.dv_action, cqe.opened_at) a
GROUP BY a.Row_Date + a.StartTime, a.Row_Date, a.DayofWeek, a.StartTime) b
GROUP BY b.row_date, b.OriginalDate, b.DayOfWeek, b.StartTime, b.CallsOffered
)c
ON c.DayofWeek = e.DayofWeek and c.StartTime = e.STARTTIME
----------------------
In order to test it, I declared the value:
Declare @StartDate as Datetime
Set @StartDate = '2015-10-10'
(The startdate can be any date but it will go back seven days.)
----------------------
You stated that the CASE statement might not be necessary at all. Is it possible to do it in order to replace the NULL value?
Thanks.
October 21, 2015 at 5:06 pm
First, create a "standard" tally table (a table of sequential numbers). I can't provide code because the filter thinks it's "sql injection". After creating the tally table, then you can do this to gen the dates and times:
Declare @StartDate as datetime
Set @StartDate = '20151010'
Select Dateadd(Minute, minutes.tally * 30, Dateadd(Day, -days.tally, @StartDate))
From (
Select Dateadd(Day, Datediff(Day, 0, @StartDate), 0) AS StartTimeMidnight
) As force_start_time_to_midnight
Inner Join dbo.tally days ON days.tally Between 0 And 6
Inner Join dbo.tally minutes ON minutes.tally >= 0 And minutes.tally < (24 * 60) / 30
Order By 1
SQL DBA,SQL Server MVP(07, 08, 09) "It's a dog-eat-dog world, and I'm wearing Milk-Bone underwear." "Norm", on "Cheers". Also from "Cheers", from "Carla": "You need to know 3 things about Tortelli men: Tortelli men draw women like flies; Tortelli men treat women like flies; Tortelli men's brains are in their flies".
October 23, 2015 at 10:16 am
Thank you very much for suggesting the tally table. This prompted me to think of using the 'with cte' statement.
I did not use the tally. But decide to use the 'with cte' and I got the result that I needed to join the subqueries.
The codes are the following:
Declare @StartDate as Datetime
Set @StartDate = '2015-10-10'
;WITH cte(DateAndHour) AS
(
SELECT @StartDate - 6
UNION ALL
SELECT DATEADD(MINUTE,30, DateAndHour)
FROM cte
WHERE DATEADD(MINUTE,30, DateAndHour) < @StartDate + 1
)
SELECT * from cte
OPTION (MAXRECURSION 0);
October 23, 2015 at 10:20 am
You need to be aware that recursion will be much, much slower, and much, much more CPU and memory overhead, than a tally table.
SQL DBA,SQL Server MVP(07, 08, 09) "It's a dog-eat-dog world, and I'm wearing Milk-Bone underwear." "Norm", on "Cheers". Also from "Cheers", from "Carla": "You need to know 3 things about Tortelli men: Tortelli men draw women like flies; Tortelli men treat women like flies; Tortelli men's brains are in their flies".
October 24, 2015 at 2:10 pm
Tamrak (10/23/2015)
Thank you very much for suggesting the tally table. This prompted me to think of using the 'with cte' statement.I did not use the tally. But decide to use the 'with cte' and I got the result that I needed to join the subqueries.
The codes are the following:
Declare @StartDate as Datetime
Set @StartDate = '2015-10-10'
;WITH cte(DateAndHour) AS
(
SELECT @StartDate - 6
UNION ALL
SELECT DATEADD(MINUTE,30, DateAndHour)
FROM cte
WHERE DATEADD(MINUTE,30, DateAndHour) < @StartDate + 1
)
SELECT * from cte
OPTION (MAXRECURSION 0);
To drive the point home that Scott just made, please read the following article on why you should NOT use rCTEs that count/increment.
http://www.sqlservercentral.com/articles/T-SQL/74118/
Shoot... even a properly formed While Loop will beat an rCTE.
--Jeff Moden
Change is inevitable... Change for the better is not.
Viewing 7 posts - 1 through 6 (of 6 total)
You must be logged in to reply to this topic. Login to reply