MySQL - Average % value from last day insertions - mysql

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);

Related

How to show data from sql table to make one of columns value column header(date)

Hello I have 2 tables in mysql DB:
mysql> describe lvlsupdate;
+--------------+-------------+------+-----+-------------------+-------------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-------------+------+-----+-------------------+-------------------+
| LvlsUpdateId | int | NO | PRI | NULL | auto_increment |
| UID | int | NO | MUL | NULL | |
| Nick | varchar(30) | NO | | NULL | |
| date | timestamp | NO | | CURRENT_TIMESTAMP | DEFAULT_GENERATED |
| Lvl | int | YES | | NULL | |
+--------------+-------------+------+-----+-------------------+-------------------+
5 rows in set (0.02 sec)
mysql> describe players;
+--------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------+------+-----+---------+----------------+
| UID | int | NO | PRI | NULL | auto_increment |
| Nick | varchar(30) | NO | UNI | NULL | |
| Active | tinyint(1) | NO | | NULL | |
+--------+-------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
In one of theme there is column date which includes timestamp value.
I'd like to create query that will show me data that there will be column Nick and 7 dates (today and 6 days before). And in each row there should be nick and lvl value from each of this dates in proper column.
For now, I've created query like this:
SELECT LvlsUpdate.nick, LvlsUpdate.lvl, LvlsUpdate.date
FROM LvlsUpdate
INNER JOIN Players ON LvlsUpdate.uid = Players.uid
WHERE Players.active = 1 AND LvlsUpdate.date > date_sub(now(), interval 7 day)
which shows me list of nicks, lvls, and date but there are duplicates of nicks, it looks like this:
+------------------+------+---------------------+
| nick | lvl | date |
+------------------+------+---------------------+
| Player1 | 124 | 2020-10-11 00:01:02 |
| Player1 | 125 | 2020-10-12 00:01:03 |
| Player1 | 125 | 2020-10-13 00:01:02 |
| Player2 | 233 | 2020-10-11 00:01:02 |
| Player2 | 233 | 2020-10-12 00:01:03 |
| Player2 | 233 | 2020-10-13 00:01:02 |
| Player3 | 164 | 2020-10-11 00:01:02 |
| Player3 | 164 | 2020-10-12 00:01:03 |
| etc....
There is reference between LvlsUpdate.UID and Players.UID. There is only 1 entry per player per day.
Is it possible to do it in sql?

Count how many entries are in a database at 5 minute intervals

I have multiple Raspberry Pi's collecting wifi beacons from mobile devices and save them in a mySQL DB. I have created a view in the DB. Each entry in the DB has the mobile device mac address, the pi id, rssi, location and a timestamp
I have created a view from multiple tables that looks like this.
+----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| pi_id | varchar(64) | NO | | NULL | |
| name | varchar(127) | NO | | NULL | |
| location | varchar(255) | NO | | NULL | |
| mac_id | varchar(200) | NO | | NULL | |
| rssi | int(11) | NO | | NULL | |
| datetime | datetime | NO | | NULL | |
+----------+--------------+------+-----+---------+-------+
For each Pi/location I want to count how many packets/beacons were seen during each 5 minute interval. I have been trying something like this.
SELECT datetime , location, count(*)
FROM packet_locations
GROUP BY DATE(DATE_SUB(datetime, INTERVAL 5 MINUTE)), location;
I want output like this:
+---------------------+----------+----------+
| datetime | location | count(*) |
+---------------------+----------+----------+
| 2016-01-26 00:00:00 | Pi1 | 44 |
| 2016-01-26 00:00:00 | Pi2 | 66 |
| 2016-01-26 00:05:00 | Pi1 | 100 |
| 2016-01-26 00:05:00 | Pi2 | 101 |
| 2016-01-26 00:10:00 | Pi1 | 128 |
| 2016-01-26 00:10:00 | Pi2 | 128 |
+---------------------+----------+----------+
SELECT concat( date_format(datetime,'%Y-%m-%d %k:')
, lpad(floor(minute(datetime)/5)*5,2,'0')
, ':00'
) datetime
, location
, count(1)
FROM packet_locations
GROUP BY date(datetime)
, hour(datetime)
, floor(minute(datetime)/5)
, location

MySQL - Select to retrieve last datetime

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);

Empty rows for MySQL Query but using a WHERE

I have a table names lcMovimientos and what I need is a query where I get as a result the sum of the quantity of cantidadMovimientos but I want each row to be by the day of the week and only to sum the days of the current week, so after researching I found the best way to do this was creating a new table with the days of the week, so I now have a table called diasSemana
SELECT * FROM diasSemana
+-----------+
| diaSemana |
+-----------+
| 0 |
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
+-----------+
and a table called lcMovimientos
mysql> DESCRIBE lcMovimientos;
+-----------------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------------+---------------+------+-----+---------+----------------+
| idMovimiento | int(11) | NO | PRI | NULL | auto_increment |
| idUsuario | int(11) | YES | | NULL | |
| tipoMovimiento | tinyint(4) | YES | | NULL | |
| cantidadMovimiento | decimal(20,2) | YES | | NULL | |
| idCategoria | int(11) | YES | | NULL | |
| fechaMovimiento | date | YES | | NULL | |
| idCuenta | int(11) | YES | | NULL | |
| descripcionMovimiento | varchar(255) | YES | | NULL | |
| etiquetasMovimiento | varchar(255) | YES | | NULL | |
+-----------------------+---------------+------+-----+---------+----------------+
I can make a query where I do get the sum of the cantidadMovimiento but when I add the where clause so I only get results from the current week, I no longer get the rows by day fo the week, so here is my query:
mysql> SELECT SUM( cantidadMovimiento ) , diaSemana, fechaMovimiento -> FROM diasSemana
-> LEFT JOIN lcMovimientos ON diaSemana = WEEKDAY( fechaMovimiento )
-> GROUP BY diaSemana;
+---------------------------+-----------+-----------------+
| SUM( cantidadMovimiento ) | diaSemana | fechaMovimiento |
+---------------------------+-----------+-----------------+
| 280.00 | 0 | 2012-02-20 |
| 800.00 | 1 | 2012-02-21 |
| 7000.00 | 2 | 2012-02-29 |
| NULL | 3 | NULL |
| NULL | 4 | NULL |
| -3300.78 | 5 | 2012-02-18 |
| 600.00 | 6 | 2012-02-26 |
+---------------------------+-----------+-----------------+
and when I use the WHERE clause:
mysql> SELECT SUM( cantidadMovimiento ) , diaSemana, fechaMovimiento
-> FROM diasSemana
-> LEFT JOIN lcMovimientos ON diaSemana = WEEKDAY( fechaMovimiento )
-> WHERE WEEK( fechaMovimiento, 1 ) = WEEK( CURRENT_DATE, 1 )
-> GROUP BY diaSemana;
+---------------------------+-----------+-----------------+
| SUM( cantidadMovimiento ) | diaSemana | fechaMovimiento |
+---------------------------+-----------+-----------------+
| 265.00 | 0 | 2012-02-20 |
| 800.00 | 1 | 2012-02-21 |
| 600.00 | 6 | 2012-02-26 |
+---------------------------+-----------+-----------------+
So my question is how can i make a query where I will get the results by the day of the week using the where to only get dates of the current week??? thank you so much in advance!
try this
SELECT
COALESCE(SUM( cantidadMovimiento ),0) AS cantidadMovimiento,
diaSemana,
DATE_ADD(DATE(NOW()), INTERVAL diaSemana-WEEKDAY(NOW()) DAY) AS weekday
FROM diasSemana
LEFT JOIN lcMovimientos
ON diaSemana = WEEKDAY( fechaMovimiento )
AND WEEK(fechaMovimiento) = WEEK(NOW()) AND YEAR(fechaMovimiento) = YEAR(NOW())
GROUP BY diaSemana;

MySQL SUM ( Query works but returns unexpected results )

I am performing a MySQL Query on two tables
keyword_stats
+-------------+---------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+---------------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| keywordid | int(11) | NO | MUL | NULL | |
| campaignid | int(11) | NO | | NULL | |
| clicks | int(11) | NO | MUL | NULL | |
| impressions | int(11) | NO | MUL | NULL | |
| cost | decimal(10,2) | NO | MUL | NULL | |
| conversions | int(11) | NO | MUL | NULL | |
| timestamp | timestamp | NO | MUL | CURRENT_TIMESTAMP | |
| statsdate | date | NO | MUL | NULL | |
+-------------+---------------+------+-----+-------------------+----------------+
AND
Keywords table
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| clientid | int(11) | NO | MUL | NULL | |
| campaignid | int(11) | NO | | NULL | |
| keywordid | int(11) | NO | MUL | NULL | |
| text | varchar(125) | NO | MUL | NULL | |
| status | varchar(10) | NO | MUL | NULL | |
+------------+--------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)
With the following SQL Query
SELECT
k.status, statsdate,
SUM( impressions ) AS impressions, SUM( clicks ) AS clicks,
SUM( conversions ) AS conversions, SUM( cost ) AS cost
FROM keyword_stats
LEFT JOIN
(
SELECT
text,keywordid,status
FROM keywords
) AS k USING (keywordid)
WHERE
campaignid = 56486451
AND statsdate BETWEEN '2011-03-01' AND '2011-03-23'
AND k.status = "enabled"
GROUP BY keywordid
ORDER BY conversions DESC, clicks DESC, impressions DESC LIMIT 0, 10
With the results of
+---------+------------+-------------+--------+-------------+-----------+
| status | statsdate | impressions | clicks | conversions | cost |
+---------+------------+-------------+--------+-------------+-----------+
| enabled | 2011-03-01 | 71256166 | 242079 | 4247 | 891572.71 |
| enabled | 2011-03-01 | 1101 | 10 | 1 | 43.19 |
| enabled | 2011-03-01 | 210 | 6 | 0 | 23.40 |
| enabled | 2011-03-01 | 331 | 4 | 0 | 15.29 |
| enabled | 2011-03-01 | 672 | 3 | 0 | 11.41 |
| enabled | 2011-03-01 | 486 | 2 | 0 | 8.93 |
| enabled | 2011-03-01 | 254 | 2 | 0 | 9.48 |
| enabled | 2011-03-01 | 2201 | 1 | 0 | 2.96 |
| enabled | 2011-03-01 | 581 | 1 | 0 | 3.25 |
| enabled | 2011-03-01 | 483 | 1 | 0 | 4.39 |
+---------+------------+-------------+--------+-------------+-----------+
10 rows in set (12.12 sec)
The query runs and performs as expected, except as you may see the first result contains unexpected results, since it is impossible for any keywords to have that amount of clicks, conversions or cost as a sum total I'm trying to figure where MySQL is combining the totals to achieve that result
EDIT ADDED KEYWORDID
+------------+---------+------------+-------------+--------+-------------+-----------+
| keywordid | status | statsdate | impressions | clicks | conversions | cost |
+------------+---------+------------+-------------+--------+-------------+-----------+
| 2147483647 | enabled | 2011-03-01 | 71256166 | 242079 | 4247 | 891572.71 |
| 101936939 | enabled | 2011-03-01 | 1101 | 10 | 1 | 43.19 |
| 23039553 | enabled | 2011-03-01 | 210 | 6 | 0 | 23.40 |
| 117364874 | enabled | 2011-03-01 | 331 | 4 | 0 | 15.29 |
| 18862051 | enabled | 2011-03-01 | 672 | 3 | 0 | 11.41 |
| 16695651 | enabled | 2011-03-01 | 486 | 2 | 0 | 8.93 |
| 14690232 | enabled | 2011-03-01 | 254 | 2 | 0 | 9.48 |
| 18046691 | enabled | 2011-03-01 | 2201 | 1 | 0 | 2.96 |
| 22232901 | enabled | 2011-03-01 | 581 | 1 | 0 | 3.25 |
| 15072731 | enabled | 2011-03-01 | 483 | 1 | 0 | 4.39 |
+------------+---------+------------+-------------+--------+-------------+-----------+
10 rows in set (11.99 sec)
keywordid is a PRIMARY KEY in neither table.
Most probably, you have a keywordid with lots of records in both tables which results in a cross join on this keywordid.
Also note that, first, a LEFT JOIN is redundant in your query since your are filtering on k.status, and, second, MySQL is not that good in optimizing inline views.
Just use this:
SELECT k.status, statsdate,
SUM( impressions ) AS impressions, SUM( clicks ) AS clicks,
SUM( conversions ) AS conversions, SUM( cost ) AS cost
FROM keyword_stats
JOIN keywords
USING (keywordid)
WHERE campaignid = 56486451
AND statsdate BETWEEN '2011-03-01' AND '2011-03-23'
AND k.status = "enabled"
GROUP BY
keywordid
ORDER BY
conversions DESC, clicks DESC, impressions DESC
LIMIT 0, 10
Do you need the information for each day? or do you need the data sum for all days?
If you want data for each day put "statsdate" in your group by expression.
Then, I thik that you don't need make a subquery. You can put the table name right in left join.
If you want the data for each "keywordid" put "keywordid" in the result fields. Status is not mandatory because always is "enabled"
Example:
SELECT
keywordid, statsdate,
SUM( impressions ) AS impressions, SUM( clicks ) AS clicks,
SUM( conversions ) AS conversions, SUM( cost ) AS cost
FROM keyword_stats
LEFT JOIN keywords k USING (keywordid)
WHERE
campaignid = 56486451
AND statsdate BETWEEN '2011-03-01' AND '2011-03-23'
AND k.status = "enabled"
GROUP BY keywordid, statsdate
ORDER BY conversions DESC, clicks DESC, impressions DESC LIMIT 0, 10