MySQL Query change row if higher? - mysql

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)

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]>

How to update or change auto increment column value in Mysql

I have a table eav_attribute which have a below structure,
I have mistakenly deleted one record from this table with auto increment attribute id column with value 961.
Now I want that column again with same attribute id value.
But when I am inserting that column it is adding with auto increment value i.e. around 1500.
I want to add new coulmn with attribute id 961
I tried to change set AUTO_INCREMENT to 961 before adding column.
ALTER TABLE eav_attribute AUTO_INCREMENT = 961;
But its not working. Please provide any suggestion.
You can override the auto increment column. For example
MariaDB [sandbox]> drop table if exists t;
Query OK, 0 rows affected (0.14 sec)
MariaDB [sandbox]> create table t (id int auto_increment primary key,val varchar(1));
Query OK, 0 rows affected (0.27 sec)
MariaDB [sandbox]> insert into t (val) values
-> ('a'),('b'),('C');
Query OK, 3 rows affected (0.03 sec)
Records: 3 Duplicates: 0 Warnings: 0
MariaDB [sandbox]>
MariaDB [sandbox]> select * from t;
+----+------+
| id | val |
+----+------+
| 1 | a |
| 2 | b |
| 3 | C |
+----+------+
3 rows in set (0.00 sec)
MariaDB [sandbox]>
MariaDB [sandbox]> delete from t where val = 'b';
Query OK, 1 row affected (0.03 sec)
MariaDB [sandbox]>
MariaDB [sandbox]> select * from t;
+----+------+
| id | val |
+----+------+
| 1 | a |
| 3 | C |
+----+------+
2 rows in set (0.00 sec)
MariaDB [sandbox]> insert into t values (2,'b');
Query OK, 1 row affected (0.02 sec)
MariaDB [sandbox]> select * from t;
+----+------+
| id | val |
+----+------+
| 1 | a |
| 2 | b |
| 3 | C |
+----+------+
3 rows in set (0.00 sec)
MariaDB [sandbox]> show create table t;
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t | CREATE TABLE `t` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`val` varchar(1) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1 |
+-------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
I would strongly advice you test this thoroughly...

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)

MySQL DEFAULT vs. MariaDB DEFAULT

I have table_a with and auto_increment column named id and string column named name.
Running the statement:
INSERT INTO table_a(id, name)VALUES(DEFAULT, 'test');
Results to (MySQL):
+----+------+
| id | name |
+----+------|
| 1 | test |
+----+------+
Running the similar statement in MariaDB results to:
+----+------+
| id | name |
+----+------|
| 0 | test |
+----+------+
Other scenario:
I tried editing the AUTO_INCREMENT value of the table to 30. MySQL inserts 30 while MariaDB inserts 0.
What is the difference of DEFAULT value in INSERT statement of MySQL and MariaDB? Is this a bug in MariaDB or it is working as intended?
This behavior is controlled by SQL_MODE='NO_AUTO_VALUE_ON_ZERO', both in MySQL and MariaDB. If you observe the difference, it's most likely because you have different sql_mode on the instances.
MariaDB [test]> CREATE TABLE t (id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY);
Query OK, 0 rows affected (0.20 sec)
MariaDB [test]> SET SQL_MODE='';
Query OK, 0 rows affected (0.00 sec)
MariaDB [test]> INSERT INTO t (id) VALUES (DEFAULT);
Query OK, 1 row affected (0.05 sec)
MariaDB [test]> SELECT * FROM t;
+----+
| id |
+----+
| 1 |
+----+
1 row in set (0.00 sec)
MariaDB [test]> DROP TABLE t;
Query OK, 0 rows affected (0.14 sec)
MariaDB [test]> CREATE TABLE t (id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY);
Query OK, 0 rows affected (0.30 sec)
MariaDB [test]> SET SQL_MODE='NO_AUTO_VALUE_ON_ZERO';
Query OK, 0 rows affected (0.00 sec)
MariaDB [test]> INSERT INTO t (id) VALUES (DEFAULT);
Query OK, 1 row affected (0.03 sec)
MariaDB [test]> SELECT * FROM t;
+----+
| id |
+----+
| 0 |
+----+
1 row 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>