time avg within a mysql database within a certain time period - mysql

so im trying to get time averages within a 20 minute period and add it from my main sql table to a secondary table the number will go into the database several time throughout the day and it works well the 1st time the number goes in but then if it goes in later in the day it will update the secondary table to a much higher avg e.g.
number 58 goes in at 12:08 am and then stops going in at 12:31am the avg will show 23 minutes if it then goes back into the table at 13:47pm and goes out at 14:13pm it will show 2 hours and 5 minute
im currently using
insert into test.time (beacon,location,date,time_avg,mac,time)
SELECT beacon,location,date,
TIMEDIFF(max(`time`),min(`time`)) AS `time_avg`,mac,time
FROM test.test where time > now() - interval 30 minute
group by beacon
ORDER BY `time_avg` DESC
how can i query it so that it add a new line for half hour or so i did try to use an event where it only queried it every 30 minutes rather than after every update but i still ended up with the same issue, i have also tried insert ignore where mac is a unique value and replace into.
I have attached a picture of my table to give an idea of the data that is in it.
example data in a string for ease
insert into test ('location','beacon','mac','date','time') VALUES (YELLOW, 1,AC3422845D, 2018-01-10, 12:08:55);
mysql table data

You have a number of things to look at and probably fix in your insert..select. If your aim is to have 1 record in your insert table per beacon,mac,date then an insert on duplicate key is probably what you want.For example
MariaDB [sandbox]> drop table if exists t;
Query OK, 0 rows affected (0.27 sec)
MariaDB [sandbox]>
MariaDB [sandbox]> create table t
-> (location varchar(20),beacon int, mac varchar(20),`date` date, `time` time);
Query OK, 0 rows affected (0.20 sec)
MariaDB [sandbox]> insert into t (location,beacon,mac,`date`,`time`) VALUES ('YELLOW', 1,'AC3422845D', '2018-01-10', '11:00:44');
Query OK, 1 row affected (0.01 sec)
MariaDB [sandbox]> insert into t (location,beacon,mac,`date`,`time`) VALUES ('YELLOW', 1,'AC3422845D', '2018-01-11', '10:00:55');
Query OK, 1 row affected (0.01 sec)
MariaDB [sandbox]> insert into t (location,beacon,mac,`date`,`time`) VALUES ('YELLOW', 1,'AC3422845D', '2018-01-11', '11:00:55');
Query OK, 1 row affected (0.05 sec)
MariaDB [sandbox]> insert into t (location,beacon,mac,`date`,`time`) VALUES ('YELLOW', 1,'AC3422845D', '2018-01-11', '12:00:55');
Query OK, 1 row affected (0.02 sec)
MariaDB [sandbox]>
MariaDB [sandbox]> drop table if exists t1;
Query OK, 0 rows affected (0.08 sec)
MariaDB [sandbox]> create table t1
-> (beacon int,location varchar(20), mac varchar(20),`date` date, maxtimetime time, mintime time, obs int, now30 datetime);
Query OK, 0 rows affected (0.26 sec)
MariaDB [sandbox]> alter table t1
-> add unique key t1k1 (beacon,mac,`date`);
Query OK, 0 rows affected (0.18 sec)
Records: 0 Duplicates: 0 Warnings: 0
MariaDB [sandbox]>
MariaDB [sandbox]>
MariaDB [sandbox]> #select * from t;
MariaDB [sandbox]> #select #now;
MariaDB [sandbox]>
MariaDB [sandbox]> truncate table t1;
Query OK, 0 rows affected (0.27 sec)
MariaDB [sandbox]> set #now = str_to_date('2018-01-10 11:15:00','%Y-%m-%d %H:%i:%s');
Query OK, 0 rows affected (0.00 sec)
MariaDB [sandbox]> insert into t1 (beacon ,mac ,`date`, maxtimetime, mintime, obs, now30)
-> select *
-> from
-> (select t.beacon,t.mac,t.`date`, max(`time`) maxtime,min(`time`) mintime,count(*) obs,
-> #now - interval 30 minute now30
-> from t
-> where `time` between time(#now - interval 30 minute) and time(#now) and `date` = date(#now)
-> group by t.beacon ,t.mac,t.`date`
-> ) s
-> on duplicate key
-> update maxtimetime = s.maxtime, mintime = s.mintime, obs = s.obs, now30 = s.now30;
Query OK, 1 row affected (0.03 sec)
Records: 1 Duplicates: 0 Warnings: 0
MariaDB [sandbox]>
MariaDB [sandbox]> select * from t1;
+--------+----------+------------+------------+-------------+----------+------+---------------------+
| beacon | location | mac | date | maxtimetime | mintime | obs | now30 |
+--------+----------+------------+------------+-------------+----------+------+---------------------+
| 1 | NULL | AC3422845D | 2018-01-10 | 11:00:44 | 11:00:44 | 1 | 2018-01-10 10:45:00 |
+--------+----------+------------+------------+-------------+----------+------+---------------------+
1 row in set (0.00 sec)
MariaDB [sandbox]>
MariaDB [sandbox]> set #now = str_to_date('2018-01-11 11:15:00','%Y-%m-%d %H:%i:%s');
Query OK, 0 rows affected (0.00 sec)
MariaDB [sandbox]> insert into t1 (beacon ,mac ,`date`, maxtimetime, mintime, obs, now30)
-> select *
-> from
-> (select t.beacon,t.mac,t.`date`, max(`time`) maxtime,min(`time`) mintime,count(*) obs,
-> #now - interval 30 minute now30
-> from t
-> where `time` between time(#now - interval 30 minute) and time(#now) and `date` = date(#now)
-> group by t.beacon ,t.mac,t.`date`
-> ) s
-> on duplicate key
-> update maxtimetime = s.maxtime, mintime = s.mintime, obs = s.obs, now30 = s.now30;
Query OK, 1 row affected (0.03 sec)
Records: 1 Duplicates: 0 Warnings: 0
MariaDB [sandbox]>
MariaDB [sandbox]> select * from t1;
+--------+----------+------------+------------+-------------+----------+------+---------------------+
| beacon | location | mac | date | maxtimetime | mintime | obs | now30 |
+--------+----------+------------+------------+-------------+----------+------+---------------------+
| 1 | NULL | AC3422845D | 2018-01-10 | 11:00:44 | 11:00:44 | 1 | 2018-01-10 10:45:00 |
| 1 | NULL | AC3422845D | 2018-01-11 | 11:00:55 | 11:00:55 | 1 | 2018-01-11 10:45:00 |
+--------+----------+------------+------------+-------------+----------+------+---------------------+
2 rows in set (0.00 sec)
MariaDB [sandbox]>
MariaDB [sandbox]> set #now = str_to_date('2018-01-11 12:15:00','%Y-%m-%d %H:%i:%s');
Query OK, 0 rows affected (0.00 sec)
MariaDB [sandbox]> insert into t1 (beacon ,mac ,`date`, maxtimetime, mintime, obs, now30)
-> select *
-> from
-> (select t.beacon,t.mac,t.`date`, max(`time`) maxtime,min(`time`) mintime,count(*) obs,
-> #now - interval 30 minute now30
-> from t
-> where `time` between time(#now - interval 30 minute) and time(#now) and `date` = date(#now)
-> group by t.beacon ,t.mac,t.`date`
-> ) s
-> on duplicate key
-> update maxtimetime = s.maxtime, mintime = s.mintime, obs = s.obs, now30 = s.now30;
Query OK, 2 rows affected (0.02 sec)
Records: 1 Duplicates: 1 Warnings: 0
MariaDB [sandbox]>
MariaDB [sandbox]> select * from t1;
+--------+----------+------------+------------+-------------+----------+------+---------------------+
| beacon | location | mac | date | maxtimetime | mintime | obs | now30 |
+--------+----------+------------+------------+-------------+----------+------+---------------------+
| 1 | NULL | AC3422845D | 2018-01-10 | 11:00:44 | 11:00:44 | 1 | 2018-01-10 10:45:00 |
| 1 | NULL | AC3422845D | 2018-01-11 | 12:00:55 | 12:00:55 | 1 | 2018-01-11 11:45:00 |
+--------+----------+------------+------------+-------------+----------+------+---------------------+
2 rows in set (0.00 sec)

Related

MariaDB default function changing PK field with auto increment to null

Take the example of the following query, I am inserting data to the teams table and teamId (type: INT) is the primary key with auto-increment set to true.
'INSERT INTO `teams` (`teamId`,`teamName`,`referralCommission`,`createdAt`,`updatedAt`,`companyId`) VALUES (DEFAULT,?,?,?,?,?);'
This query runs fine on MySQL, but on MariaDB the DEFAULT is being converted to null, which I know is the normal behavior when the default is not set for a column. But in my case, the teamId is auto-incremented so the default should point to the next available id. Instead, teamId is set to 0 (converts from null) for all entries and since the teamId is primary key, I am unable to add new entries to the table.
Any way I can use the default function of MySQL in mariadb? or any other solution for this problem.
P.S I know I can remove the teamId field entirely from the query and it will work, but I need the above query to work as it is.
i cant say what you doing. which MariaDB version you are using ?
sample
MariaDB [bernd]> SELECT VERSION();
+----------------------------------------+
| VERSION() |
+----------------------------------------+
| 10.2.41-MariaDB-1:10.2.41+maria~bionic |
+----------------------------------------+
1 row in set (0.06 sec)
MariaDB [bernd]>
MariaDB [bernd]> TRUNCATE pk_default;
Query OK, 0 rows affected (0.09 sec)
MariaDB [bernd]> SELECT * FROM `pk_default`;
Empty set (0.01 sec)
MariaDB [bernd]> INSERT INTO `pk_default` (`id`, `sid`, `val`)
-> VALUES
-> (DEFAULT, 6, 45);
Query OK, 1 row affected (0.00 sec)
MariaDB [bernd]> SELECT * FROM `pk_default`;
+----+-----+------+
| id | sid | val |
+----+-----+------+
| 1 | 6 | 45 |
+----+-----+------+
1 row in set (0.00 sec)
MariaDB [bernd]> INSERT INTO `pk_default` (`id`, `sid`, `val`)
-> VALUES
-> (DEFAULT, 6, 45);
Query OK, 1 row affected (0.01 sec)
MariaDB [bernd]> SELECT * FROM `pk_default`;
+----+-----+------+
| id | sid | val |
+----+-----+------+
| 1 | 6 | 45 |
| 2 | 6 | 45 |
+----+-----+------+
2 rows in set (0.00 sec)
MariaDB [bernd]> INSERT INTO `pk_default` (`id`, `sid`, `val`)
-> VALUES
-> (DEFAULT, 6, 45);
Query OK, 1 row affected (0.00 sec)
MariaDB [bernd]> SELECT * FROM `pk_default`;
+----+-----+------+
| id | sid | val |
+----+-----+------+
| 1 | 6 | 45 |
| 2 | 6 | 45 |
| 3 | 6 | 45 |
+----+-----+------+
3 rows in set (0.01 sec)
MariaDB [bernd]>

MySQL Query change row if higher?

I have two Tables (account2017) and (account2018) and I want to add a 2 at the end of the names in the name row for one of the tables, but only if both tables contain the same name. Adding the 2 for that name, which has lower points value.
Overall a solution to merge two tables with unique key (name), but to decide which row gets a 2 added at his end of name, should be followed by lower points.
For example if table account2017 and account2018 have both "Alex" in the name column, add a 2 at the end of the name (=Alex2) to that table, which has lower value in points column. As Alex in accounts2017 has 20 points, and Alex in accounts2018 has only 15 points, Alex name will be changed to Alex2 for accounts2018. Accounts2017 will be untouched.
Any idea how it can work?
If I'm understanding correctly, sounds like you need to use 2 separate update statements, using exists to match the criteria:
update account2017
set name = concat(name, '2')
where exists (
select 1
from account2018
where account2017.name = account2018.name and account2017.score < account2018.score)
update account2018
set name = concat(name, '2')
where exists (
select 1
from account2017
where account2018.name = account2017.name and account2018.score < account2017.score)
You will need to do this in 2 queries. Syntax will depend on what you are using (MySQL, SQL Server, SQLite) but here is the MySQL Version:
UPDATE accounts2017 table1 SET name = concat(name, '2') WHERE exists (SELECT 1 FROM accounts2018 table2 WHERE table1.name = table2.name AND table1.score < table2.score);
Then you can just flip the query around to update the 2018 table.
You can do this using a multi-table update. This relies on mysql recognising no change has been made to account2017 (proved by the fact that timestamp has not changed) but beware both before and after triggers fire.
MariaDB [sandbox]> drop table if exists account2017,account2018;
Query OK, 0 rows affected (0.39 sec)
MariaDB [sandbox]> create table account2017(name varchar(10), points int,ts timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);
Query OK, 0 rows affected (0.20 sec)
MariaDB [sandbox]> create table account2018(name varchar(10), points int,ts timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);
Query OK, 0 rows affected (0.29 sec)
MariaDB [sandbox]>
MariaDB [sandbox]> drop trigger if exists t;
Query OK, 0 rows affected, 1 warning (0.00 sec)
MariaDB [sandbox]> delimiter $$
MariaDB [sandbox]> create trigger t before update on account2017
-> for each row
-> begin
-> insert into debug_table(msg) values (concat('before:',old.name,':',new.name));
-> end $$
Query OK, 0 rows affected (0.07 sec)
MariaDB [sandbox]> delimiter ;
MariaDB [sandbox]>
MariaDB [sandbox]> drop trigger if exists t1;
Query OK, 0 rows affected, 1 warning (0.00 sec)
MariaDB [sandbox]> delimiter $$
MariaDB [sandbox]> create trigger t1 after update on account2017
-> for each row
-> begin
-> insert into debug_table(msg) values (concat('after:',old.name,':',new.name));
-> end $$
Query OK, 0 rows affected (0.08 sec)
MariaDB [sandbox]> delimiter ;
MariaDB [sandbox]>
MariaDB [sandbox]> insert into account2017 (name,points) values('alex',20);
Query OK, 1 row affected (0.02 sec)
MariaDB [sandbox]> insert into account2018 (name,points) values('alex',15);
Query OK, 1 row affected (0.01 sec)
MariaDB [sandbox]> truncate table debug_table;
Query OK, 0 rows affected (0.17 sec)
MariaDB [sandbox]>
MariaDB [sandbox]> select * from account2017;
+------+--------+---------------------+
| name | points | ts |
+------+--------+---------------------+
| alex | 20 | 2018-12-11 16:49:25 |
+------+--------+---------------------+
1 row in set (0.00 sec)
MariaDB [sandbox]> select * from account2018;
+------+--------+---------------------+
| name | points | ts |
+------+--------+---------------------+
| alex | 15 | 2018-12-11 16:49:25 |
+------+--------+---------------------+
1 row in set (0.00 sec)
MariaDB [sandbox]>
MariaDB [sandbox]> select sleep(60);
+-----------+
| sleep(60) |
+-----------+
| 0 |
+-----------+
1 row in set (1 min 0.00 sec)
MariaDB [sandbox]> update account2017 join account2018 on account2017.name = account2018.name
-> set account2017.name = case when account2017.points < account2018.points then concat(account2017.name,'2') else account2017.name end,
-> account2018.name = case when account2018.points < account2017.points then concat(account2018.name,'2') else account2018.name end
-> where 1 = 1;
Query OK, 1 row affected (0.04 sec)
Rows matched: 2 Changed: 1 Warnings: 0
MariaDB [sandbox]>
MariaDB [sandbox]>
MariaDB [sandbox]>
MariaDB [sandbox]> select * from account2017;
+------+--------+---------------------+
| name | points | ts |
+------+--------+---------------------+
| alex | 20 | 2018-12-11 16:49:25 |
+------+--------+---------------------+
1 row in set (0.00 sec)
MariaDB [sandbox]> select * from account2018;
+-------+--------+---------------------+
| name | points | ts |
+-------+--------+---------------------+
| alex2 | 15 | 2018-12-11 16:50:26 |
+-------+--------+---------------------+
1 row in set (0.00 sec)
MariaDB [sandbox]> select * from debug_table;
+----+------------------+------+
| id | msg | MSG2 |
+----+------------------+------+
| 1 | before:alex:alex | NULL |
| 2 | after:alex:alex | NULL |
+----+------------------+------+
2 rows in set (0.00 sec)

Mysql crashed on conditional insert

I need some condition on insert statement to prevent unauthorized insertions.
I wrote something like this:
INSERT INTO `fund` (amount,description)
SELECT 1000,'Some description'
WHERE 12 IN (SELECT id FROM users WHERE allow_add=1)
Where 12 is the id of current user.
But mysql process stopped unexpectedly!
I use XAMPP with MySQL version: 5.5.5-10.1.13-MariaDB.
Note that I ran this code before this in SQL Server without any problem.
Any Idea?
From users and Where exists work so maybe a bug with in?
MariaDB [sandbox]> delete from t where att = 3;
Query OK, 2 rows affected (0.04 sec)
MariaDB [sandbox]>
MariaDB [sandbox]> select * from t;
+------+------+
| id | att |
+------+------+
| 1 | 1 |
| 1 | 2 |
| 2 | 0 |
+------+------+
3 rows in set (0.00 sec)
MariaDB [sandbox]>
MariaDB [sandbox]> insert into t(id,att)
-> select 4,3
-> from users
-> where id = 1;
Query OK, 1 row affected (0.05 sec)
Records: 1 Duplicates: 0 Warnings: 0
MariaDB [sandbox]>
MariaDB [sandbox]>
MariaDB [sandbox]> select * from t;
+------+------+
| id | att |
+------+------+
| 1 | 1 |
| 1 | 2 |
| 2 | 0 |
| 4 | 3 |
+------+------+
4 rows in set (0.00 sec)
MariaDB [sandbox]>
MariaDB [sandbox]> insert into t(id,att)
-> select 4,3
-> where exists (select 1 from users where id = 1);
Query OK, 1 row affected (0.02 sec)
Records: 1 Duplicates: 0 Warnings: 0
MariaDB [sandbox]>
MariaDB [sandbox]> select * from t;
+------+------+
| id | att |
+------+------+
| 1 | 1 |
| 1 | 2 |
| 2 | 0 |
| 4 | 3 |
| 4 | 3 |
+------+------+
5 rows in set (0.00 sec)
Add semicolon(;) to your query, and what desc is doing in query. It will describe the table structure and its attributes.
It is not a proper way to authorize insertions in database. Instead, you can use programming based solution for this problem.
In PHP, a proper solution could be:-
if ($user->allow_add == 1){ //where $user is the User instance for current user
$sql->query("INSERT INTO `fund` (amount,desc) VALUES(1000,'Some desc')");
}
Try This:
INSERT INTO `fund` (amount,desc)
SELECT 1000 as amt,'Some desc' as des FROM users WHERE allow_add=1 LIMIT 12
With thanks to P.Salmon answer, I found the solution. It seems that MySQL needs FROM statement in conditional SELECT, unlike the SQL Server. So, I add a temporary table name as below:
INSERT INTO `fund` (amount,description)
SELECT 1000,'Some description'
FROM (SELECT 1) t
WHERE 12 IN (SELECT id FROM users WHERE allow_add=1)

MySQL: delete row if exist in other table with condition

I need to delete rows from 'old_battles' table, if it exists in 'battles' table with condition:
delete the row from 'old_battles' if it existed in 'battles' and 'old_battles.status = "finished"'
note: old_battles.id = battles.id
tables structure:
battles:
id status
1 finished
2 cancelled
3 on progress
4 finished
5 finished
old_battles:
id status
1 finished
2 cancelled
3 on progress
4 finished
5 finished
my query:
delete from old_battles
where old_battles.id in
(
select ob2.id
from old_battles ob2,battles b
where ob2.id = b.id
and ob2.status = 'finished'
)
Consider the following
mysql> create table battles (id int, status varchar(100));
Query OK, 0 rows affected (0.09 sec)
mysql> insert into battles values
-> (1,'finished'),
-> (2,'cancelled'),
-> (3,'on progress'),
-> (4,'finished'),
-> (5,'finished');
Query OK, 5 rows affected (0.03 sec)
Records: 5 Duplicates: 0 Warnings: 0
mysql> create table old_battles like battles;
Query OK, 0 rows affected (0.11 sec)
mysql> insert into old_battles values
-> (1,'finished'),
-> (2,'cancelled'),
-> (3,'on progress'),
-> (4,'finished'),
-> (5,'finished');
Query OK, 5 rows affected (0.03 sec)
Records: 5 Duplicates: 0 Warnings: 0
The following is the query to delete
delete ob from old_battles ob
join battles b on b.id = ob.id where ob.status = 'finished';
mysql> select * from old_battles ;
+------+-------------+
| id | status |
+------+-------------+
| 2 | cancelled |
| 3 | on progress |
+------+-------------+
2 rows in set (0.00 sec)

mysql delete triggers

I think I read that the delete trigger doesn't know what data was deleted and loops over the whole table applying the trigger. Is that true?
Does that mean that the before delete loops over the whole table before the data is deleted and after delete loops over the whole table after the delete occurs?
Is there no way to loop over just the deleted records? So If 10 records are deleted loop over them?
DELIMITER $$
DROP TRIGGER `before_delete_jecki_triggername`$$
CREATE TRIGGER before_delete_triggername
BEFORE DELETE ON table
FOR EACH ROW
BEGIN
/*do stuff*/
END$$
DELIMITER ;
Thanks,
Mat
I think it was due to a confusion with FOR EACH ROW statement.
It is only for "matched records for the statement issued before trigger is invoked."
If there exists N number of records in a table and matches records for where id=x,
assuming x causes a result of less than N records, say N-5, then
FOR EACH ROW causes a loop for N-5 times only.
UPDATE:
A sample test run on the rows affected due to FOR EACH ROW statement is shown below.
mysql> -- create a test table
mysql> drop table if exists tbl; create table tbl ( i int, v varchar(10) );
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.06 sec)
mysql> -- set test data
mysql> insert into tbl values(1,'one'),(2,'two' ),(3,'three'),(10,'ten'),(11,'eleven');
Query OK, 5 rows affected (0.02 sec)
Records: 5 Duplicates: 0 Warnings: 0
mysql> select * from tbl;
+------+--------+
| i | v |
+------+--------+
| 1 | one |
| 2 | two |
| 3 | three |
| 10 | ten |
| 11 | eleven |
+------+--------+
5 rows in set (0.02 sec)
mysql> select count(*) row_count from tbl;
+-----------+
| row_count |
+-----------+
| 5 |
+-----------+
1 row in set (0.00 sec)
mysql>
mysql> -- record loop count of trigger in a table
mysql> drop table if exists rows_affected; create table rows_affected( i int );
Query OK, 0 rows affected (0.02 sec)
Query OK, 0 rows affected (0.05 sec)
mysql> select count(*) 'rows_affected' from rows_affected;
+---------------+
| rows_affected |
+---------------+
| 0 |
+---------------+
1 row in set (0.00 sec)
mysql>
mysql> set #cnt=0;
Query OK, 0 rows affected (0.00 sec)
mysql>
mysql> -- drop trigger if exists trig_bef_del_on_tbl;
mysql> delimiter //
mysql> create trigger trig_bef_del_on_tbl before delete on tbl
-> for each row begin
-> set #cnt = if(#cnt is null, 1, (#cnt+1));
->
-> /* for cross checking save loop count */
-> insert into rows_affected values ( #cnt );
-> end;
-> //
Query OK, 0 rows affected (0.00 sec)
mysql>
mysql> delimiter ;
mysql>
mysql> -- now let us test the delete operation
mysql> delete from tbl where i like '%1%';
Query OK, 3 rows affected (0.02 sec)
mysql>
mysql> -- now let us see what the loop count was
mysql> select #cnt as 'cnt';
+------+
| cnt |
+------+
| 3 |
+------+
1 row in set (0.00 sec)
mysql>
mysql> -- now let us see the table data
mysql> select * from tbl;
+------+-------+
| i | v |
+------+-------+
| 2 | two |
| 3 | three |
+------+-------+
2 rows in set (0.00 sec)
mysql> select count(*) row_count from tbl;
+-----------+
| row_count |
+-----------+
| 2 |
+-----------+
1 row in set (0.00 sec)
mysql> select count(*) 'rows_affected' from rows_affected;
+---------------+
| rows_affected |
+---------------+
| 3 |
+---------------+
1 row in set (0.00 sec)
mysql>