Environment
Table agent_poll records the total calls a call centre agent makes, polling the telephone system every 1 second to request the updated total. This provides many records per agent per day.
This is described as follows.
DESCRIBE agent_poll
Field |Type |Null|Key|Default |Extra |
-------------|------------|----|---|--------------------|--------------|
agent_poll_id|int(11) |NO |PRI| |auto_increment|
poll_time |timestamp(6)|NO | |CURRENT_TIMESTAMP(6)| |
agent_id |int(11) |NO |MUL| | |
agent_status |int(11) |NO |MUL| | |
total_calls |int(11) |NO | | | |
Here's the top ten rows - junk demo data so not as regular as it would be in production.
select * FROM agent_poll
agent_poll_id|poll_time |agent_id|agent_status|total_calls|
-------------|-----------------------------|--------|------------|-----------|
1| 2019-11-12 12:02:01| 1| 1| 12|
2| 2019-11-12 12:30:01| 4| 1| 12|
3| 2019-11-12 12:34:18| 6| 4| 22|
4| 2019-11-12 12:44:07| 1| 4| 22|
5| 2019-11-14 12:15:44| 3| 3| 4|
6| 2019-11-14 12:16:07| 1| 3| 23|
7| 2019-11-14 12:21:42| 2| 3| 4|
8| 2019-11-14 12:21:58| 5| 3| 4|
9| 2019-11-14 12:22:47| 1| 1| 25|
10| 2019-11-14 12:30:57| 2| 1| 4|
Additionally, here is the agent status table.
select * from agent_status
agent_status_id|agent_status_description|
---------------|------------------------|
1|Available |
2|Break |
3|Admin |
4|On a Call |
5|Sick |
6|Holiday |
7|Away |
Problem
How do you write this query?
- If agent_poll.agent_status is 5, 6 or 7, return agent_status, else
- Return the maximum total_calls calls taken by each agent for each week day
Restrictions
- Should be dynamic to allow for future table expansion - more agents, agent status codes etc
- Should always look up the most recent date
Output should look like this.
Agent|Mon|Tue|Wed|Thu|Fri|
-----|---|---|---|---|---|
1| | | | | |
2| | | | | |
3| | | | | |
4| | | | | |
5| | | | | |
6| | | | | |
7| | | | | |
8| | | | | |
9| | | | | |
10| | | | | |
11| | | | | |
12| | | | | |
13| | | | | |
What I have Tried
I know that it is possible to pivot given the correct permissions. Since I am outputting to Grafana, which can only have read-only permissions, I cannot CREATE
, UPDATE
, or DROP
.
One aproach is to use a virtual table. This was suggested to me by a TSQL dev.
;WITH beepboop AS (
SELECT B.agent_id,
CASE WHEN WEEKDAY(B.poll_time) = 'Monday' THEN MAX(B.total_calls) ELSE NULL END AS 'Monday Calls', #one bin for the data to go into
CASE WHEN WEEKDAY(B.poll_time) = 'Tuesday' THEN MAX(B.total_calls) ELSE NULL END AS 'Tuesday Calls',
CASE WHEN WEEKDAY(B.poll_time) = 'Wednesday' THEN MAX(B.total_calls) ELSE NULL END AS 'Wednesday Calls',
CASE WHEN WEEKDAY(B.poll_time) = 'Thursday' THEN MAX(B.total_calls) ELSE NULL END AS 'Thursday Calls',
CASE WHEN WEEKDAY(B.poll_time) = 'Friday' THEN MAX(B.total_calls) ELSE NULL END AS 'Friday Calls'
FROM agent_poll AS B
WHERE B.poll_time > GETDATE() -7 --the last week
GROUP BY B.agent_id, DATENAME(WEEKDAY, B.poll_time) #Have to group by the datename as well as we're using it as part of the filter so it can't be aggregated
)
SELECT BB.agent_id,
MAX(BB.[Monday Calls]) AS 'Monday Calls', #now we are only grouping by the agent so we aggregate the bins
MAX(BB.[Tuesday Calls]) AS 'Tuesday Calls',
MAX(BB.[Wednesday Calls]) AS 'Wednesday Calls',
MAX(BB.[Thursday Calls]) AS 'Thursday Calls',
MAX(BB.[Friday Calls]) AS 'Friday Calls'
FROM beepboop AS BB
GROUP BY BB.agent_id # only group by agent now
Unfortunately, I have not been successful in getting this to work in MySQL. I am therefore left with the assumption that it needs to be built from many sub-queries, but cannot get them in the right places. This returns the agent_id along with the dates for the current week.
SELECT agent_id as "Agent",
STR_TO_DATE(CONCAT(yearweek(CURRENT_TIMESTAMP),' Monday'), '%X%V %W') as "Mon",
STR_TO_DATE(CONCAT(yearweek(CURRENT_TIMESTAMP),' Tuesday'), '%X%V %W') as "Tue",
STR_TO_DATE(CONCAT(yearweek(CURRENT_TIMESTAMP),' Wednesday'), '%X%V %W') as "Wed",
STR_TO_DATE(CONCAT(yearweek(CURRENT_TIMESTAMP),' Thursday'), '%X%V %W') as "Thu",
STR_TO_DATE(CONCAT(yearweek(CURRENT_TIMESTAMP),' Friday'), '%X%V %W') as "Fri"
from agent
order by Agent
Agent|Mon |Tue |Wed |Thu |Fri |
-----|----------|----------|----------|----------|----------|
1|2019-11-18|2019-11-19|2019-11-20|2019-11-21|2019-11-22|
2|2019-11-18|2019-11-19|2019-11-20|2019-11-21|2019-11-22|
3|2019-11-18|2019-11-19|2019-11-20|2019-11-21|2019-11-22|
4|2019-11-18|2019-11-19|2019-11-20|2019-11-21|2019-11-22|
5|2019-11-18|2019-11-19|2019-11-20|2019-11-21|2019-11-22|
6|2019-11-18|2019-11-19|2019-11-20|2019-11-21|2019-11-22|
7|2019-11-18|2019-11-19|2019-11-20|2019-11-21|2019-11-22|
8|2019-11-18|2019-11-19|2019-11-20|2019-11-21|2019-11-22|
9|2019-11-18|2019-11-19|2019-11-20|2019-11-21|2019-11-22|
10|2019-11-18|2019-11-19|2019-11-20|2019-11-21|2019-11-22|
I believe I just need to extend each of the day lines to use the dates they provide as a condition. Where should I go from here?