MySQL - Select to retrieve last datetime - mysql

I've got a table in MySQL:
| period_duration | duration | sample | corner | country | partner | ok_rate
+---------------------+----------+--------+----------+---------+-----------------------+-------------------------
| 2014-12-15 17:00:00 | 3600 | 1 | GRPS_INB | ARG | Charlie | 98 |
| 2014-12-15 17:00:00 | 3600 | 1 | GRPS_INB | DEU | Jack | 90 |
| 2014-12-15 17:00:00 | 3600 | 1 | GRPS_INB | NLD | Will | 100 |
| 2014-12-15 20:00:00 | 3600 | 1 | GRPS_INB | ARG | Charlie | 98 |
| 2014-12-15 20:00:00 | 3600 | 1 | GRPS_INB | DEU | Jack | 90 |
| 2014-12-15 20:00:00 | 3600 | 1 | GRPS_INB | NLD | Will | 100 |
+-----------------+-------------+------+-----+---------------------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+-------------+------+-----+---------------------+-------+
| period_duration | datetime | NO | PRI | 0000-00-00 00:00:00 | |
| duration | varchar(6) | YES | | NULL | |
| sample | varchar(2) | YES | | NULL | |
| corner | varchar(10) | YES | | NULL | |
| country | varchar(60) | NO | PRI | | |
| partner | varchar(60) | NO | PRI | | |
| ok_rate | int(8) | YES | | NULL | |
+-----------------+-------------+------+-----+---------------------+-------+
This table increases from hour to hour.
I need a shellscript that will check each line from the last hour and that has an "ok_rate" lower than a given value, and return them to me on a select.
The select should bring country, the partner, and the ok_rate.
Example:
Let's say I want it to be done with <=98%¨on "ok_rate".
My returning rows would be:
| 2014-12-15 20:00:00 | 3600 | 1 | GRPS_INB | ARG | Charlie | 98 |
| 2014-12-15 20:00:00 | 3600 | 1 | GRPS_INB | DEU | Jack | 90 |
So far, I could only make it bring me the values below 98%, but not those that are also the last datetime that exists:
select country, partner, ok_rate from TABLE where ok_rate <= '98'
But how can I add a WHERE clause the makes it understand I want the last existing datetime that exists on period_duration too?
I mean something like:
SELECT country, partner, ok_rate FROM TABLE WHERE pdp_in_ok_rate <=98 AND (period_duration IS THE LAST ONE)?

This query should return what you want:
SELECT country, partner, ok_rate
FROM TABLE WHERE ok_rate <= 98
AND period_duration = (SELECT MAX(period_duration)
FROM TABLE)

Look in to GROUP BY for more detail because I'm not exactly sure what you want but something like this should help:
SELECT country, partner, ok_rate FROM TABLE
WHERE ok_rate <= '98'
GROUP BY `partner`, `country`
HAVING period_duration = MAX(period_duration);

Related

Trailing n-day cumulative sum in mysql

I have this structure:
+--------------------------------------+---------------------+--------+-------------+-------------+
| id | start | User | billedHours | trail90dsum |
+--------------------------------------+---------------------+--------+-------------+-------------+
| 2e88f9f9-2543-11eb-9d57-02b150913215 | 2018-10-04 11:00:00 | User 1 | 15.30 | NULL |
| 2e89af0a-2543-11eb-9d57-02b150913215 | 2018-10-09 12:00:00 | User 1 | 0.40 | NULL |
| 2e8a400b-2543-11eb-9d57-02b150913215 | 2018-10-09 17:00:00 | User 2 | 0.60 | NULL |
| 2e8ae87d-2543-11eb-9d57-02b150913215 | 2018-10-25 17:30:00 | User 2 | 0.30 | NULL |
| 2e8ba472-2543-11eb-9d57-02b150913215 | 2018-10-27 15:00:00 | User 3 | 1.20 | NULL |
| 2e975c93-2543-11eb-9d57-02b150913215 | 2018-10-29 17:30:00 | User 3 | 0.30 | NULL |
| 2e980477-2543-11eb-9d57-02b150913215 | 2018-11-02 13:30:00 | User 1 | 1.90 | NULL |
| 2e98a874-2543-11eb-9d57-02b150913215 | 2018-11-03 12:00:00 | User 2 | 0.70 | NULL |
| 2e993a7d-2543-11eb-9d57-02b150913215 | 2018-11-04 13:30:00 | User 3 | 1.30 | NULL |
| 2ea9fa03-2543-11eb-9d57-02b150913215 | 2018-11-11 11:00:00 | User 1 | 0.90 | NULL |
+--------------------------------------+---------------------+--------+-------------+-------------+
I am looking for an UPDATE query that will fill the trail90dsum field with SUM(billedHours) for each user within the trailing 90 days (as of each start date).
I was able to construct a SELECT query with a join for reporting the data, but I can't transform it to work in the UPDATE syntax.
Thanks,
Phillip
Thanks for all the help. This query got the job done:
UPDATE mytable dst JOIN
(SELECT t1.user, t1.start, t1.billedHours, SUM(t2.billedHours) as last90
FROM mytable as t1 JOIN mytable as t2 ON DATEDIFF(t1.start, t2.start) BETWEEN 0
AND 90 WHERE t1.user=t2.user
GROUP BY t1.user, t1.start, t1.billedHours) src
SET dst.trail90dsum=src.last90
WHERE src.start=dst.start and src.user=dst.user
Thanks, -P

Mysql - Calculate Times per month - organise result

I'm extracting data from sql by the following SQL Query
SELECT DISTINCT
SEC_TO_TIME(SUM(TIME_TO_SEC(transics_bco.arab))) AS arab,
transics_bco.plate
FROM transics_bco
WHERE transics_bco.extdate BETWEEN '2019-12-01' AND '2019-12-31'
GROUP BY transics_bco.plate
This gives me the following result:
-----------------------
| ARAB | Plate |
-----------------------
| 178:44:43 | 1ABC123 |
| 156:23:44 | 1DEF456 |
-----------------------
Is it possible to get the result shown as this;
---------------------------------------------------------------
| Plate | December 19 | January 20 | February 20 | March 20 |
---------------------------------------------------------------
| 1ABC123 | 178:44:43 | 120:34:56 | ... | ... |
| 1DEF456 | 156:23:44 | 102:34:54 | ... | ... |
| 1GHI789 | 111:22:33 | 156:35:35 | ... | ... |
---------------------------------------------------------------
SQL Sample: transics_bco
----------------------------------------
| id | plate | arab | extdate |
----------------------------------------
| 1 | 1ABC123 | 00:14:23 | 2019-12-01 |
| 2 | 1ABC123 | 00:10:20 | 2019-12-03 |
| 3 | 1ABC123 | 00:45:06 | 2019-12-07 |
| 4 | 1ABC123 | 00:54:45 | 2020-01-02 |
| 5 | 1ABC123 | 00:26:10 | 2020-01-03 |
| 6 | 1ABC123 | 00:43:28 | 2020-01-04 |
----------------------------------------
Would greatly appreciate pointers in the good direction
Adding db describe as requested in the comments;
-
Adding describe of Transics_bco as requested in the comments
===================================================================================================================================================================================================================================================================================================================
| Field | Type | Null | Key | Default | Extra |
===================================================================================================================================================================================================================================================================================================================
| id | int(11) | NO | PRI | null | auto_increment |
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| plate | varchar(255) | NO | | null | |
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| arab | time | NO | | 00:00:00 | |
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| extdate | date | NO | | null | |
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SELECT
plate,
december19,
january20,
february20,
march20
FROM
(
SELECT DISTINCT
a.plate,
(
CASE
WHEN
Month(a.extdate) = 12
AND Year(a.extdate) = 2019
THEN
Sec_to_time(Sum(Time_to_sec(a.arab)))
END
)
AS 'December19',
(
CASE
WHEN
Month(a.extdate) = 1
AND Year(a.extdate) = 2020
THEN
a.arab
END
)
AS 'January20, (CASE WHEN MONTH(a.extDate)=2 AND YEAR(a.extDate)=2020 THEN SEC_TO_TIME(SUM(TIME_TO_SEC(a.arab))) END) AS 'february20', (CASE WHEN MONTH(a.extDate)=3 AND YEAR(a.extDate)=2020 THEN SEC_TO_TIME(SUM(TIME_TO_SEC(a.arab))) END) AS 'march20', FROM transics_bco a WHERE transics_bco.extdate BETWEEN '2019-12-01' AND '2019-12-31'
GROUP BY
transics_bco.plate
)
T
GROUP BY
T.plate;

Error when joining a table to itself

I have a table where the data of measured temperature and humidity is stored. Records with temperature have the field meas_kind set to "T", and for humidity it is set to "H".
mysql> describe meteo;
+-----------+---------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+---------------------+------+-----+---------+----------------+
| id | bigint(20) unsigned | NO | PRI | NULL | auto_increment |
| meas_time | timestamp | YES | | NULL | |
| room | varchar(10) | NO | | NULL | |
| meas_kind | char(1) | NO | | NULL | |
| value | double | NO | | NULL | |
+-----------+---------------------+------+-----+---------+----------------+
mysql> select * from meteo;
+----+---------------------+------+-----------+-------+
| id | meas_time | room | meas_kind | value |
+----+---------------------+------+-----------+-------+
| 35 | 2017-05-24 16:51:47 | 123 | T | 22.61 |
| 36 | 2017-05-24 16:51:47 | 123 | H | 36.93 |
| 37 | 2017-05-24 16:51:51 | 123 | T | 22.61 |
| 38 | 2017-05-24 16:51:51 | 123 | H | 36.94 |
| 39 | 2017-05-24 16:51:56 | 123 | T | 22.61 |
| 40 | 2017-05-24 16:51:56 | 123 | H | 36.94 |
+----+---------------------+------+-----------+-------+
Temperature and humidity are measured in the same time, so I want this table to be like this:
+---------------------+------+-------+-------+
| meas_time | room | Temp | Humid |
+---------------------+------+-------+-------+
| 2017-05-24 16:51:47 | 123 | 22.61 | 36.93 |
| 2017-05-24 16:51:51 | 123 | 22.61 | 36.94 |
| 2017-05-24 16:51:56 | 123 | 22.61 | 36.94 |
+---------------------+------+-------+-------+
I've tried to make this query, but it gives me an error:
ERROR 1242 (21000): Subquery returns more than 1 row
Please help me to get a correct result.
select
m.meas_time,
m.room,
(select value from meteo m1 where m1.meas_kind='T' and m.meas_time=m1.meas_time) as Temp,
(select value from meteo m2 where meas_kind='H' and m.meas_time=m2.meas_time) as Humid
from meteo m
join meteo m1
on m.meas_time=m1.meas_time
and m.room=m1.room
join meteo m2
on m.meas_time=m2.meas_time
and m.room=m2.room
group by m.room, m.meas_time;
You are overcomplicating things. A simple pivot query can give you the results you want.
SELECT
meas_time,
room,
MAX(CASE WHEN meas_kind = 'T' THEN value END) AS Temp,
MAX(CASE WHEN meas_kind = 'H' THEN value END) AS Humid
FROM meteo
GROUP BY meas_time, room

MySQL - Average % value from last day insertions

I've got a table in MySQL:
+-----------------+-------------+------+-----+---------------------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+-------------+------+-----+---------------------+-------+
| period_duration | datetime | NO | PRI | 0000-00-00 00:00:00 | |
| duration | varchar(6) | YES | | NULL | |
| sample | varchar(2) | YES | | NULL | |
| corner | varchar(10) | YES | | NULL | |
| country | varchar(60) | NO | PRI | | |
| roaming_partner | varchar(60) | NO | PRI | | |
| pdp_in_total | int(8) | YES | | NULL | |
| pdp_in_ok | int(8) | YES | | NULL | |
| pdp_in_not_ok | int(8) | YES | | NULL | |
| pdp_in_ok_rate | int(8) | YES | | NULL | |
+-----------------+-------------+------+-----+---------------------+-------+
This table has new insertions hourly, that makes many different period_duration per roaming_partner:
+---------------------+----------+--------+----------+---------+-----------------------+--------------+-----------+---------------+----------------+
| period_duration | duration | sample | corner | country | roaming_partner | pdp_in_total | pdp_in_ok | pdp_in_not_ok | pdp_in_ok_rate |
+---------------------+----------+--------+----------+---------+-----------------------+--------------+-----------+---------------+----------------+
| 2014-12-16 14:00:00 | 3600 | 1 | GPRS_OUT | USA | Operator1 | 796 | 787 | 9 | 99 |
| 2014-12-16 15:00:00 | 3600 | 1 | GPRS_OUT | USA | Operator1 | 1748 | 1706 | 42 | 98 |
| 2014-12-16 16:00:00 | 3600 | 1 | GPRS_OUT | USA | Operator1 | 7 | 7 | 0 | 100 |
"ok_rate" is a percentage rate.
I need to create a SELECT that will show every single country, roaming_partner and pdp_in_ok_rate from the last 24 insertions, with the average pdp_in_ok_rate% from these insertions.
It is like i wanted that my SQL query say:
"This is the average pdp_in_ok_rate in the last 24 insertions for every operator on your table. Not in the whole table, but from these last ones."
Can someone please help me?
Does this do what you want?
select country, roaming_partner, avg(pd_in_ok_rate) as avgrate
from table t
where period_duration >= date_sub(now(), interval -1 day)
group by country, roaming_partner;
This doesn't give you the detail on the average. You can use this as a subquery, if you want the detail as well
select t.*, cr.avgrate
from table t join
(select country, roaming_partner, avg(pd_in_ok_rate) as avgrate
from table t
where period_duration >= date_sub(now(), interval -1 day)
group by country, roaming_partner
) cr
on t.country = cr.country and t.roaming_partner = cr.roaming_partner
where period_duration >= date_sub(now(), interval -1 day);

Fetch cumulative sum from MySQL table

I have a table containing donations, and I am now creating a page to view statistics. I would like to fetch monthly data from the database with gross and cumulative gross.
mysql> describe donations;
+------------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| transaction_id | varchar(64) | NO | UNI | | |
| donor_email | varchar(255) | NO | | | |
| net | double | NO | | 0 | |
| gross | double | NO | | NULL | |
| original_request | text | NO | | NULL | |
| time | datetime | NO | | NULL | |
| claimed | tinyint(4) | NO | | NULL | |
+------------------+------------------+------+-----+---------+----------------+
Here's what I've tried:
SET #cgross = 0;
SELECT YEAR(`time`), MONTH(`time`), SUM(`gross`), (#cgross := #cgross + SUM(`gross`)) AS `cumulative_gross` FROM `donations` GROUP BY YEAR(`time`), MONTH(`time`);
The result is:
+--------------+---------------+--------------+------------------+
| YEAR(`time`) | MONTH(`time`) | SUM(`gross`) | cumulative_gross |
+--------------+---------------+--------------+------------------+
| 2013 | 1 | 257 | 257 |
| 2013 | 2 | 140 | 140 |
| 2013 | 3 | 311 | 311 |
| 2013 | 4 | 279 | 279 |
+--------------+---------------+--------------+------------------+
Which is wrong. The desired result would be:
+--------------+---------------+--------------+------------------+
| YEAR(`time`) | MONTH(`time`) | SUM(`gross`) | cumulative_gross |
+--------------+---------------+--------------+------------------+
| 2013 | 1 | 257 | 257 |
| 2013 | 2 | 140 | 397 |
| 2013 | 3 | 311 | 708 |
| 2013 | 4 | 279 | 987 |
+--------------+---------------+--------------+------------------+
I tried this without SUM, and it did work as expected.
SET #cgross = 0;
SELECT YEAR(`time`), MONTH(`time`), SUM(`gross`), (#cgross := #cgross + 10) AS `cumulative_gross` FROM `donations` GROUP BY YEAR(`time`), MONTH(`time`);
+--------------+---------------+--------------+------------------+
| YEAR(`time`) | MONTH(`time`) | SUM(`gross`) | cumulative_gross |
+--------------+---------------+--------------+------------------+
| 2013 | 1 | 257 | 10 |
| 2013 | 2 | 140 | 20 |
| 2013 | 3 | 311 | 30 |
| 2013 | 4 | 279 | 40 |
+--------------+---------------+--------------+------------------+
Why doesn't it work with SUM? Any ideas how I could fix it?
Thanks,
Lassi
A subquery without variables will do it just as easily, and quite a bit more portably;
SELECT YEAR(`time`),
MONTH(`time`),
SUM(gross),
(SELECT SUM(gross)
FROM donations
WHERE `time`<=MAX(a.`time`)) cumulative_gross
FROM donations a GROUP BY YEAR(`time`), MONTH(`time`);
An SQLfiddle to test with.