From a Call Detail Record (CDR) table, I need to compute the maximum channels that have been simultaneously busy in a specified time range. The table has one column for the end of the call time and another column for the call duration.
CallID DateTime Duration
1 2014-04-28 11:37:54 35
2 2014-04-28 11:37:53 82
3 2014-04-28 11:37:42 53
4 2014-04-28 11:37:37 159
5 2014-04-28 11:37:13 49
6 2014-04-28 11:37:02 267
7 2014-04-28 11:37:00 267
8 2014-04-28 11:36:54 49
9 2014-04-28 11:36:20 266
I would need a report for getting a response like this (time range in hours for example):
DateRange NumBusyChannels
2014-04-28 11:00-12:00 9
2014-04-28 10:00-11:00 5
EDIT: Sample table to test Miky response.
CallID DateTime Duration
014 2013-07-23 08:42:42 3
015 2013-07-23 08:42:42 3
019 2013-07-23 08:42:42 3
012 2013-07-23 08:10:00 3
013 2013-07-23 08:10:00 3
016 2013-07-23 08:10:00 3
017 2013-07-23 08:10:00 3
018 2013-07-23 08:10:00 3
You might start with a query like this which should give you the number of overlapping calls for each call.
SELECT COuter.*,
COALESCE(COverlap.Cnt,0) as NumChannelsInUse
FROM Cdr COuter
LEFT OUTER JOIN(
SELECT C1.CallId,
COUNT(*) as Cnt
FROM Cdr C1
INNER JOIN Cdr C2
ON (C2.DateTime >= C1.DateTime
AND
C2.DateTime <= DATE_ADD(C1.DateTime, INTERVAL C1.Duration SECOND))
OR
(DATE_ADD(C2.DateTime, INTERVAL C2.Duration SECOND) >= C1.DateTime
AND
DATE_ADD(C2.DateTime, INTERVAL C2.Duration SECOND) <= DATE_ADD(C1.DateTime, INTERVAL C1.Duration SECOND))
OR
(C1.DateTime >= C2.DateTime
AND
C1.DateTime <= DATE_ADD(C2.DateTime, INTERVAL C2.Duration SECOND) )
OR
(DATE_ADD(C1.DateTime, INTERVAL C1.Duration SECOND) >= C2.DateTime
AND
DATE_ADD(C1.DateTime, INTERVAL C1.Duration SECOND) < DATE_ADD(C2.DateTime, INTERVAL C2.Duration SECOND))
GROUP BY C1.CallId) COverlap
ON COuter.CallId = COverlap.CallId
You would then have to further manipulate the query to partition the results by hour and then to select the maximum for each hour..
Related
I have these rows in my Database Table.
ID Name Date working_hours
29 A 2020-04-07 14.45
29 A 2020-04-08 10.30
29 A 2020-04-06 06.30
29 A 2020-04-10 10.15
30 B 2020-04-09 09.15
30 B 2020-04-07 09.00
30 B 2020-04-08 09.00
30 B 2020-04-10 04.45
30 B 2020-04-06 07.45
30 B 2020-04-10 04.45
When I execute below Query
SELECT ID,Name, date, working_hours,sum(working_hours) as 'total_week_hours'
from tblstafftasks
WHERE date between
date_add('2020-04-10', interval -WEEKDAY('2020-04-10') day) and
date_add(date_add('2020-04-10', interval -WEEKDAY('2020-04-10')-1 day), interval 6 day)
group by ID
I Get below OUTPUT
ID Name Date working_hours total_week_hours
29 A 2020-04-10 10.15 41.2
30 B 2020-04-10 04.45 43.5
But I want output to look like below
ID Name Date working_hours total_week_hours
29 A 2020-04-07 14.45 41.2
29 A 2020-04-08 10.30 41.2
29 A 2020-04-06 06.30 41.2
29 A 2020-04-10 10.15 41.2
30 B 2020-04-09 09.15 43.5
30 B 2020-04-07 09.00 43.5
30 B 2020-04-08 09.00 43.5
30 B 2020-04-10 04.45 43.5
30 B 2020-04-06 07.45 43.5
30 B 2020-04-10 04.45 43.5
Any help will be highly appreciated.
Join the original table with a subquery that gets the weekly totals.
SELECT t1.ID, t1.Name, t1.date, t1.working_hours, t2.total_week_hours
FROM tblstafftasks AS t1
JOIN (
SELECT ID, SUM(working_hours) AS total_week_hours
WHERE date between
date_add('2020-04-10', interval -WEEKDAY('2020-04-10') day) and
date_add(date_add('2020-04-10', interval -WEEKDAY('2020-04-10')-1 day), interval 6 day
GROUP BY ID)
) AS t2 ON t1.ID = t2.ID
WHERE t1.date between
date_add('2020-04-10', interval -WEEKDAY('2020-04-10') day) and
date_add(date_add('2020-04-10', interval -WEEKDAY('2020-04-10')-1 day), interval 6 day)
My table have fields that represent starting and ending working period as datetime.
I need to find related entries that match a total of 14hours min over a sliding period of 24 hours.
I think window function will (maybe) save me, but MariadDB (i use) doesn't implement yet Range time intervals in window function.
here is some example data:
id starting_hour ending_hour
-- ------------------- -------------------
1 2018-09-02 06:00:00 2018-09-02 08:30:00
2 2018-09-03 08:30:00 2018-09-03 10:00:00
4 2018-09-03 11:00:00 2018-09-03 15:00:00
5 2018-09-02 15:30:00 2018-09-02 16:00:00
6 2018-09-02 16:15:00 2018-09-02 17:00:00
7 2018-09-20 00:00:00 2018-09-20 08:00:00
8 2018-09-19 10:00:00 2018-09-19 12:00:00
9 2018-09-19 12:00:00 2018-09-19 16:00:00
10 2018-10-08 12:00:00 2018-10-08 14:00:00
11 2018-10-29 09:00:00 2018-10-29 10:00:00
So how to find rows where in a 24 hours window their sum a more or equal to 14 hours.
thanks
Edit:
SELECT
id,
starting_hour,
ending_hour,
TIMEDIFF (ending_hour, starting_hour) AS duree,
(
SELECT SUM(TIMEDIFF(LEAST(ending_hour, DATE_ADD(a.starting_hour, INTERVAL 24 HOUR)), starting_hour)) / 10000
FROM `table` b
WHERE b.starting_hour BETWEEN a.starting_hour AND DATE_ADD(a.starting_hour, INTERVAL 24 HOUR)
) AS duration
FROM
`table` a
HAVING duration >= 14
ORDER BY starting_hour ASC
;
This returns Id 8 but i want the whole period. (eg: Id 8, Id 9 and Id 7)
EDIT2:
The expected results are ranges of working time where they are in a window of 24 hours and where their sum are more or equal to 14 hours.
EDIT 3:
In fact under MySQL 8 this seems to work.
SELECT * FROM (
SELECT
*,
SEC_TO_TIME(SUM(TIME_TO_SEC(TIMEDIFF(hs.`ending_hour`, hs.`starting_hour`))) OVER (ORDER BY hs.starting_hour RANGE BETWEEN INTERVAL '12' HOUR PRECEDING AND INTERVAL '12' HOUR following)) AS tot
FROM
table hs
WHERE hs.`starting_hour` > DATE_SUB(NOW(), INTERVAL 50 DAY) AND hs.`ending_hour` <= NOW()
ORDER BY hs.`starting_hour` ASC
) t1
HAVING tot >= '14:00:00'
;
Is there a way to do it under MariaDB 10.2 without window function ? Or without window range function ?
My table votes contains votes that have been made by users at different times:
id item_id position user_id created_at
1 2 0 1 11/21/2013 11:27
26 1 1 1 11/21/2013 11:27
27 3 2 1 11/21/2013 11:27
42 2 2 1 12/7/2013 2:20
41 3 1 1 12/7/2013 2:20
40 1 0 1 12/7/2013 2:20
67 2 2 1 12/13/2013 1:13
68 1 1 1 12/13/2013 1:13
69 3 0 1 12/13/2013 1:13
84 2 0 1 12/28/2013 2:29
83 3 2 1 12/28/2013 2:29
82 1 1 1 12/28/2013 2:29
113 3 0 1 1/17/2014 22:08
114 1 1 1 1/17/2014 22:08
115 2 2 1 1/17/2014 22:08
138 2 0 1 1/20/2014 16:49
139 1 1 1 1/20/2014 16:49
140 3 2 1 1/20/2014 16:49
141 1 1 11 1/20/2014 16:51
142 3 2 11 1/20/2014 16:51
143 2 0 11 1/20/2014 16:51
I need to tally the results on a monthly basis but here's the tricky part: the start/end of the month does not necessarily fall on the first day of the month. So if the votes are due on the 10th day of every month, I need a vote that was cast on the 10th to be in a different group from a vote that was cast on the 11th. Using the data above, I want to get three groups:
Group 1: 6 votes (11/21 and 12/7)
Group 2: 6 votes (12/13, 12/28)
Group 3: 9 votes (1/17, 1/20)
I've tried a lot of approaches but to no avail. This is my query right now:
select created_at, ADDDATE(DATE_FORMAT(created_at, '%Y-%m-01'),interval 10 day) as duedate,count("id") from votes where list_id = 2 group by duedate
I am getting group sizes of 3, 9, and 9, not 6, 6 and 9. Any help you can provide would be much appreciated. Thanks.
Your query is close. You just need to subtract 9 days (10 - 1) from the current day to get the month:
select created_at, date_sub(created_at, interval 9 day) as duedate,
count(id)
from votes
where list_id = 2
group by duedate;
date_format() converts a date to a string. There is no need to convert a date value to a character value for this query.
EDIT:
To group by month:
select date_format(date_sub(created_at, interval 9 day), '%Y-%m') as YYYYMM,
count(id)
from votes
where list_id = 2
group by YYYYMM;
I have a favorite table with 4 columns
employee_id
product_id
frequency
last_consumed_date
Now i'm getting the 6 rows with the highest frequency for the employee_id with a minimal frequency of 6.
Example with employee_id 1
SELECT * FROM `favorites`
WHERE `employee_id` = 1
AND `frequency` >= 6
ORDER BY `frequency` DESC LIMIT 0,6
So far so good!
But now i want to prefer the rows if the last_consumed_date is within a month (30 days), So i must do something with:
DATE_SUB(CURDATE(),INTERVAL 30 DAY) <= `lastchanged`
Here is a table example to make it more clear
Table filled:
1 5 11 2012-10- 3
1 13 8 2012-11- 7
1 18 20 2012- 9-25
1 42 10 2012-11- 3
1 28 15 2012-10-17
1 9 7 2012-10- 8
1 64 9 2012-11- 1
2 24 8 2012- 8-28
2 12 5 2012-10-16
2 5 12 2012-11-11
Today is 2012-11- 8
30 days back is 2012-10- 9
Table returned after SQL:
1 28 15 2012-10-17 <Sorted by 30 days interval and frequency>
1 42 10 2012-11- 3
1 64 9 2012-11- 1
1 13 8 2012-11- 7
1 18 20 2012- 9-25 <Sorted by frequency>
1 5 11 2012-10- 3
Now the question is, How do i order those 2 things in 1 query?
First an order by the date (with 30 days interval)
and than an order by the frequency of seperated results (inside interval and all others)
Ohh i think i found my answer by trial-error ^v^
SELECT * FROM `favorites`
WHERE `employee_id` = 1
AND `frequency` >= 6
ORDER BY (DATE_SUB(CURDATE(),INTERVAL 30 DAY) <= `lastchanged`) DESC,
`frequency` DESC
LIMIT 0,6
For those who tried helping! Thank you
I have a table
date d_id r_id p_id q_sold onhand
2012-10-10 5 1 3025 3 10
2012-10-10 5 1 3022 12 20
2012-10-10 5 1 3023 15 33
2012-10-11 5 1 3025 3 10
2012-10-11 5 1 3022 12 20
2012-10-11 5 1 3023 15 33
2012-10-12 5 1 3025 3 10
2012-10-12 5 1 3022 12 20
2012-10-12 5 1 3023 15 33
2012-10-13 5 1 3025 3 10
2012-10-13 5 1 3022 12 20
2012-10-13 5 1 3023 15 33
2012-10-14 5 1 3025 3 10
2012-10-14 5 1 3022 12 10
2012-10-14 5 1 3023 15 33
2012-10-15 5 1 3025 3 5
2012-10-15 5 1 3022 12 5
2012-10-15 5 1 3023 15 33
I would like to get the result of the q_sold divided by average of the onhand over a 5 day period, while displaying the other data for a specific date like the 2012-10-15.
I create a query
set #stdate = '2012-10-10';
set #endate = '2012-10-15';
SELECT date, d_id,r_id,p_id,q_sold,onhand,qty_sold/AVG(qty_onhand)
FROM stp_vwsales_info_tots
WHERE date BETWEEN #stdate and #endate and d_id=5
GROUP BY d_id,r_id,p_id
But the result being showed is incorrect, it displays the data for the 2012-10-10 instead of 2010-10-15
date d_id r_id p_id q_sold onhand avg
2012-10-10 5 1 3022 12 20 0.7579
2012-10-10 5 1 3023 15 33 0.4545
2012-10-10 5 1 3025 3 10 0.3273
Can anyone help?
Use your #stdate and #endate as DATE(#stdate/#endate) or DATE_FORMAT(#stdate/#endate,'%Y-%m-%d') otherwise you have to convert #stdate/#endate from string to date through MySQL
i think what your looking for is something called a simple moving average.
to calculate this you'll need to use an inline subquery - so performance won't be the best.
assuming you want to calculate the average over the previous 5 day period, try something like this:
SELECT
date, d_id, r_id, p_id, q_sold, onhand,
( SELECT q_sold/AVG(t2.onhand)
FROM stp_vwsales_info_tots AS t2
WHERE p_id=t1.p_id AND DATEDIFF(t1.date, t2.date) BETWEEN 0 AND 4
) AS 'moving_avg'
FROM stp_vwsales_info_tots AS t1
GROUP BY t1.p_id,t1.date
order by t1.date;