MySQL: delete row if exist in other table with condition - mysql

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)

Related

time avg within a mysql database within a certain time period

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)

INSERT INTO with empty results from SELECT

I'm trying to insert into table A from the results gather from table B:
INSERT INTO A (x, y, created_at)
(SELECT x, "something", a_timestamp
FROM B WHERE c IS NULL AND a_timestamp > NOW())
The issue is that, for some instances
(SELECT x, "something", a_timestamp
FROM B WHERE c IS NULL AND a_timestamp > NOW())
doesn't return any records (which is okay), but then the other INSERT fails.
How can I cover myself from that scenario?
Thanks!
I can't reproduce the error:
mysql> DROP TABLE IF EXISTS `tbl_test`;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> CREATE TABLE IF NOT EXISTS `tbl_test` (
-> `id` TINYINT
-> );
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO `tbl_test`
-> SELECT 1
-> FROM DUAL
-> WHERE 0 = 0;
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> SELECT `id` FROM `tbl_test`;
+------+
| id |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
mysql> INSERT INTO `tbl_test`
-> SELECT 1
-> FROM DUAL
-> WHERE 0 = 1;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> SELECT `id` FROM `tbl_test`;
+------+
| id |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
UPDATE
mysql> DROP TABLE IF EXISTS `tbl_test`;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE IF NOT EXISTS `tbl_test` (
-> `id` TINYINT
-> );
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO `tbl_test`
-> (`id`)
-> VALUES
-> (101);
Query OK, 1 row affected (0.00 sec)
mysql> SELECT `id`
-> FROM `tbl_test`;
+------+
| id |
+------+
| 101 |
+------+
1 row in set (0.00 sec)
mysql> INSERT INTO `tbl_test`
-> SELECT `id` + 1
-> FROM `tbl_test`
-> WHERE `id` > 100;
Query OK, 1 row affected (0.00 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> SELECT `id`
-> FROM `tbl_test`;
+------+
| id |
+------+
| 101 |
| 102 |
+------+
2 rows in set (0.00 sec)
mysql> INSERT INTO `tbl_test`
-> SELECT `id` + 1
-> FROM `tbl_test`
-> WHERE `id` < 100;
Query OK, 0 rows affected (0.00 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> SELECT `id`
-> FROM `tbl_test`;
+------+
| id |
+------+
| 101 |
| 102 |
+------+
2 rows in set (0.00 sec)
See db-fiddle.
You can use INSERT IGNORE INTO to address your issue.
For example:
INSERT IGNORE INTO A (x, y, created_at)
(SELECT x, "something", a_timestamp
FROM B WHERE c IS NULL AND a_timestamp > NOW())
More info can be found here
"INSERT INTO A (x, y, created_at)
(SELECT x, \"something\", a_timestamp
FROM B WHERE c IS NULL AND a_timestamp > \"#{current_time}\")
To
"INSERT INTO A (x, y, created_at)
(SELECT x, \"something\", a_timestamp
FROM B WHERE c IS NULL AND a_timestamp > \"#{current_time}\")
AND (SELECT count(x) FROM B WHERE c IS NULL AND a_timestamp > \"#{current_time}\")) > 0"

How do I roll up multiple detail rows' columns into a single column?

I have two tables:
table_a:
ID | NAME
===============
1 | DAN
2 | RON
3 | JANE
table_b:
ID | TEXT
===============
2 | APPLE
2 | BANANA
2 | COFFEE
I need to get the results for ID 2.
I was thinking that even if I got a string containing the TEXT's values for ID 2 from table_b would be great for example:
ID | NAME | TEXT
=============================
2 | RON | APPLE,BANANA,COFFEE
Is this even possible?
SELECT
A.*,GROUP_CONCAT(B.`TEXT`) `TEXT`
FROM
table_a A INNER JOIN table_b B USING (ID)
WHERE A.ID=2;
Here is a sample
mysql> DROP TABLE IF EXISTS table_a;
Query OK, 0 rows affected (0.03 sec)
mysql> DROP TABLE IF EXISTS table_b;
Query OK, 0 rows affected (0.03 sec)
mysql> CREATE TABLE table_a
-> (ID int not null auto_increment,
-> NAME VARCHAR(20),primary key (ID));
Query OK, 0 rows affected (0.13 sec)
mysql> CREATE TABLE table_b
-> (ID int not null,`TEXT` TEXT,key (ID));
Query OK, 0 rows affected (0.06 sec)
mysql> INSERT INTO table_a (NAME) VALUES ('DAN'),('RON'),('JANE');
Query OK, 3 rows affected (0.06 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> INSERT INTO table_b (ID,`TEXT`) VALUES
-> (2,'APPLE'),(2,'BANANA'),(2,'COFFEE');
Query OK, 3 rows affected (0.05 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> SELECT A.*,GROUP_CONCAT(B.`TEXT`) `TEXT`
-> FROM table_a A INNER JOIN table_b B USING (ID) WHERE A.ID=2;
+----+------+---------------------+
| ID | NAME | TEXT |
+----+------+---------------------+
| 2 | RON | APPLE,BANANA,COFFEE |
+----+------+---------------------+
1 row in set (0.00 sec)
Give it a Try !!!
To get all values available in table_a and anything that can be grouped from table_b:
SELECT
A.*,IFNULL(GROUP_CONCAT(B.`TEXT`),'') `TEXT`
FROM
table_a A LEFT JOIN table_b B USING (ID)
GROUP BY A.ID
Here is that sample:
mysql> use test
Database changed
mysql> DROP TABLE IF EXISTS table_a;
Query OK, 0 rows affected (0.03 sec)
mysql> DROP TABLE IF EXISTS table_b;
Query OK, 0 rows affected (0.02 sec)
mysql> CREATE TABLE table_a (ID int not null auto_increment,NAME VARCHAR(20),primary key (ID));
Query OK, 0 rows affected (0.01 sec)
mysql> CREATE TABLE table_b (ID int not null,`TEXT` TEXT,key (ID));
Query OK, 0 rows affected (0.03 sec)
mysql> INSERT INTO table_a (NAME) VALUES ('DAN'),('RON'),('JANE');
Query OK, 3 rows affected (0.02 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> INSERT INTO table_b (ID,`TEXT`) VALUES (2,'APPLE'),(2,'BANANA'),(2,'COFFEE');
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> SELECT A.*,IFNULL(GROUP_CONCAT(B.`TEXT`),'') `TEXT`
-> FROM table_a A LEFT JOIN table_b B USING (ID) GROUP BY A.ID;
+----+------+---------------------+
| ID | NAME | TEXT |
+----+------+---------------------+
| 1 | DAN | |
| 2 | RON | APPLE,BANANA,COFFEE |
| 3 | JANE | |
+----+------+---------------------+
3 rows in set (0.00 sec)
mysql>
you only need to use GROUP_CONCAT
SELECT a.ID, a.Name, GROUP_CONCAT(b.text) textList
FROM table_a a
INNER JOIN table_b b
ON a.ID = b.ID
-- WHERE ...if you want extra condition.
GROUP BY a.ID, a.Name
SQLFiddle Demo
GROUP_CONCAT
You can use the GROUP_CONCAT function in MySQL to combine results from a related table:
select
a.id,
a.name,
group_concat(b.text) text
from
table_a a
join
table_b b on a.id = b.id
group by a.id
Sample Output:
| ID | NAME | TEXT |
------------------------------------
| 2 | RON | APPLE,BANANA,COFFEE |
Demo: http://www.sqlfiddle.com/#!2/e3584/9

How do I insert the key 0 into mysql for AUTO_INCREMENT row? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to force MySQL to take 0 as a valid auto-increment value
I know I can do an update on an existing row, but is it possible to INSERT a row with the id 0?
mysql> create table inc( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, sz TEXT);
Query OK, 0 rows affected (0.10 sec)
mysql> insert into inc(id, sz) select 25, "a";
Query OK, 1 row affected (0.02 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> insert into inc(id, sz) select 25, "a";
ERROR 1062 (23000): Duplicate entry '25' for key 'PRIMARY'
mysql> insert into inc(id, sz) select 27, "b";
Query OK, 1 row affected (0.04 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> insert into inc(id, sz) select -5, "c";
Query OK, 1 row affected (0.03 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> insert into inc(id, sz) select 0, "d";
Query OK, 1 row affected (0.15 sec)
Records: 1 Duplicates: 0 Warnings: 0
mysql> select * from inc;
+----+------+
| id | sz |
+----+------+
| -5 | c |
| 25 | a |
| 27 | b |
| 28 | d |
+----+------+
4 rows in set (0.00 sec)
From http://dev.mysql.com/doc/refman/5.0/en/example-auto-increment.html
"No value was specified for the AUTO_INCREMENT column, so MySQL assigned sequence numbers automatically. You can also explicitly assign NULL or 0 to the column to generate sequence numbers."
So it seems using 0 just tells it to auto_increment.
But if you are assigning ID numbers, I'm not sure why you have defined the column to use AUTO_INCREMENT?

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>