What's wrong with this simple query? - mysql

I did a very simple query yesterday but this morning I couldn't remember how I did it, and whatever I tried doesn't work.
I want to do a simple SELECT COUNT(*) and then update table TEST. We want how many values from column start are (table1) are between the values in column txStart and column txEnd (from table TEST).
The SELECT COUNT(*) alone works well.
mysql> SELECT COUNT(*) FROM table1, TEST where table1.start BETWEEN TEST.txStart AND TEST.txEnd;
+----------+
| COUNT(*) |
+----------+
| 95149 |
+----------+
1 row in set (0.03 sec)
The UPDATE never happened.
mysql> UPDATE TEST
SET rdc_1ips =
SELECT COUNT(*) FROM table1, TEST WHERE table1.start between TEST.txStart AND TEST.txEnd;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT COUNT(*) FROM table1, TEST WHERE table1.start between TEST.txStart A' at line 1
Here is a preview of the table1 and table TEST
mysql> SELECT * from table1 limit 2;
+----+--------+------+---------+---------+------+-------+
| id | strand | chr | start | end | name | name2 |
+----+--------+------+---------+---------+------+-------+
| 1 | - | 1 | 2999997 | 3000096 | NULL | NULL |
| 2 | + | 1 | 2999998 | 3000097 | NULL | NULL |
+----+--------+------+---------+---------+------+-------+
mysql> SELECT * FROM TEST;
+------+-----------+--------------+-------+---------+---------+----------+
| chr | pos_start | name | name2 | txStart | txEnd | rdc_1ips |
+------+-----------+--------------+-------+---------+---------+----------+
| 1 | 3204575 | NM_001011874 | Xkr4 | 3204562 | 3661579 | 0 |
+------+-----------+--------------+-------+---------+---------+----------+

Put the sub-select in brackets.
Additionally I would give the inner "test" table an alias (just to be sure)
SET rdc_1ips =
(SELECT COUNT(*) FROM table1, TEST t2
WHERE table1.start between t2.txStart AND t2.txEnd)
But I'm not sure if this will work even if the syntax is correct. MySQL has some obnoxious limitiations when it comes to selecting from the same table that you want to update.

Related

What is wrong in this Update query which tried to update table using concat() fun

I want to update the field with appending data into it, but it is giving an error, please correct me (Query and Table desc are below)
I tried to fire UPDATE command with CONCAT () FUNCTION in SQL.
update products a
set a.des = (select concat((select b.des from products b limit 1) ,' one okay') from a)
where a.p_id = 1;
I have used MySQL,
Table Description:
mysql> desc products;
+---------+-------------+------+-----+--------------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+--------------+-------+
| p_id | int(3) | NO | PRI | 0 | |
| p_name | varchar(10) | YES | | NULL | |
| p_price | int(10) | YES | | NULL | |
| cat_id | int(3) | YES | MUL | NULL | |
| des | varchar(30) | YES | | Good | |
+---------+-------------+------+-----+--------------+-------+
Expected Output :
mysql> select * from products;
+------+--------+---------+--------+---------------+
| p_id | p_name | p_price | cat_id | des |
+------+--------+---------+--------+---------------+
| 1 | Mouse | 150 | 3 | Good one okay |
| 2 | LAN | 50 | 4 | Good |
+------+--------+---------+--------+---------------+
2 rows in set (0.00 sec)
Output Came :
Error -
update products a set a.des =
(select concat((select b.des from products b limit 1) ,' one okay')
from a) where a.p_id = 1 Error Code: 1146. Table 'test.a' doesn't exist 0.437 sec
MySQL does not allow you to reference the table being updated in the rest of the update statement, as a general rule.
The normal work-around is to phrase this as a JOIN:
update products p cross join
(select * from products limit 1) arbitrary
set p.des = concat(arbitrary.des, ' one okay')
where p.p_id = 1;
Note the use of the alias arbitrary. You are using limit with no order by so you are getting an arbitrary description.
If you just want to append a string to the existing description, then you want the simpler:
update products p
set p.des = concat(p.des, ' one okay')
where p.p_id = 1;

MySQL 5.7 JSON column update

I am using MySQL 5.7. I have a table with a JSON column.
MySQL [test_db]> select * from mytable;
+----+-------+---------------------+
| id | name | hobby |
+----+-------+---------------------+
| 1 | Rahul | {"Game": "Cricket"} |
| 2 | Sam | null |
+----+-------+---------------------+
Here, for row id = 2, I want to insert a data. I did -
update mytable set hobby = JSON_SET(hobby, '$.Game', 'soccer') where id = 2;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
It seems like data inserted properly, But when I checked
MySQL [test_db]> select * from mytable;
+----+-------+---------------------+
| id | name | hobby |
+----+-------+---------------------+
| 1 | Rahul | {"Game": "Cricket"} |
| 2 | Sam | null |
+----+-------+---------------------+
data is not inserted, Can anybody give some hint, what I am missing here.
Thanks.
Hobby is NULL, and you can't set a property on NULL, so use an IF statement instead, to convert null to an empty object first (Or initialize hobby as an empty object instead of NULL):
UPDATE mytable
SET hobby = JSON_SET(IF(hobby IS NULL, '{}', hobby), '$.Game', 'soccer')
WHERE id = 2;
Alternatitvely, use COALESCE:
UPDATE mytable
SET hobby = JSON_SET(COALESCE(hobby, '{}'), '$.Game', 'soccer')
WHERE id = 2;
See dbfiddle here.

MySQL, how to merge table duplicates entries [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How can I remove duplicate rows?
Remove duplicates using only a MySQL query?
I have a large table with ~14M entries. The table type is MyISAM ans not InnoDB.
Unfortunately, I have some duplicate entries in this table that I found with the following request :
SELECT device_serial, temp, tstamp, COUNT(*) c FROM up_logs GROUP BY device_serial, temp, tstamp HAVING c > 1
To avoid these duplicates in the future, I want to convert my current index to a unique constraint using SQL request :
ALTER TABLE up_logs DROP INDEX UK_UP_LOGS_TSTAMP_DEVICE_SERIAL,
ALTER TABLE up_logs ADD INDEX UK_UP_LOGS_TSTAMP_DEVICE_SERIAL ( `tstamp` , `device_serial` )
But before that, I need to clean up my duplicates!
My question is : How can I keep only one entry of my duplicated entries? Keep in mind that my table contain 14M entries, so I would like avoid loops if it is possible.
Any comments are welcome!
Creating a new unique key on the over columns you need to have as uniques will automatically clean the table of any duplicates.
ALTER IGNORE TABLE `table_name`
ADD UNIQUE KEY `key_name`(`column_1`,`column_2`);
The IGNORE part does not allow the script to terminate after the first error occurs. And the default behavior is to delete the duplicates.
Since MySQL allows Subqueries in update/delete statements, but not if they refer to the table you want to update, I´d create a copy of the original table first. Then:
DELETE FROM original_table
WHERE id NOT IN(
SELECT id FROM copy_table
GROUP BY column1, column2, ...
);
But I could imagine that copying a table with 14M entries takes some time... selecting the items to keep when copying might make it faster:
INSERT INTO copy_table
SELECT * FROM original_table
GROUP BY column1, column2, ...;
and then
DELETE FROM original_table
WHERE id IN(
SELECT id FROM copy_table
);
It was some time since I used MySQL and SQL in general last time, so I´m quite sure that there is something with better performance - but this should work ;)
This is how you can delete duplicate rows... I'll write you my example and you'll need to apply to your code. I have Actors table with ID and I want to delete the rows with repeated first_name
mysql> select actor_id, first_name from actor_2;
+----------+-------------+
| actor_id | first_name |
+----------+-------------+
| 1 | PENELOPE |
| 2 | NICK |
| 3 | ED |
....
| 199 | JULIA |
| 200 | THORA |
+----------+-------------+
200 rows in set (0.00 sec)
-Now I use a Variable called #a to get the ID if the next row have the same first_name(repeated, null if it's not).
mysql> select if(first_name=#a,actor_id,null) as first_names,#a:=first_name from actor_2 order by first_name;
+---------------+----------------+
| first_names | #a:=first_name |
+---------------+----------------+
| NULL | ADAM |
| 71 | ADAM |
| NULL | AL |
| NULL | ALAN |
| NULL | ALBERT |
| 125 | ALBERT |
| NULL | ALEC |
| NULL | ANGELA |
| 144 | ANGELA |
...
| NULL | WILL |
| NULL | WILLIAM |
| NULL | WOODY |
| 28 | WOODY |
| NULL | ZERO |
+---------------+----------------+
200 rows in set (0.00 sec)
-Now we can get only duplicates ID:
mysql> select first_names from (select if(first_name=#a,actor_id,null) as first_names,#a:=first_name from actor_2 order by first_name) as t1;
+-------------+
| first_names |
+-------------+
| NULL |
| 71 |
| NULL |
...
| 28 |
| NULL |
+-------------+
200 rows in set (0.00 sec)
-the Final Step, Lets DELETE!
mysql> delete from actor_2 where actor_id in (select first_names from (select if(first_name=#a,actor_id,null) as first_names,#a:=first_name from actor_2 order by first_name) as t1);
Query OK, 72 rows affected (0.01 sec)
-Now lets check our table:
mysql> select count(*) from actor_2 group by first_name;
+----------+
| count(*) |
+----------+
| 1 |
| 1 |
| 1 |
...
| 1 |
+----------+
128 rows in set (0.00 sec)
it works, if you have any question write me back

A weird error in Matlab with MySQL

I have two tables named t1 and t2, which content list as following:
mysql> use test;
Database changed
mysql> select * from t1;
+----+------+
| id | val |
+----+------+
| 1 | 100 |
| 2 | 200 |
+----+------+
2 rows in set (0.00 sec)
mysql> select * from t2;
+----+-------+
| id | val |
+----+-------+
| -1 | -1000 |
| 1 | 1000 |
| 3 | 3000 |
+----+-------+
3 rows in set (0.00 sec)
There is a sql statement run in mysql command with on problem:
mysql> create or replace view iid as select id from t1 union select id from t2;select iid.id,t1.val,t2.val from iid left join t1 on iid.id=t1.id left join t2 on iid.id=t2.id;
Query OK, 0 rows affected (0.07 sec)
+----+------+-------+
| id | val | val |
+----+------+-------+
| 1 | 100 | 1000 |
| 2 | 200 | NULL |
| -1 | NULL | -1000 |
| 3 | NULL | 3000 |
+----+------+-------+
4 rows in set (0.00 sec)
While it run in matlab with a error:
>> sqlCmd = ['create or replace view iid as select id from t1 union select id from t2;',...
'select iid.id,t1.val,t2.val from iid',...
' left join t1 on iid.id=t1.id',...
' left join t2 on iid.id=t2.id'];
conn = database('test','root','198471',...
'com.mysql.jdbc.Driver','jdbc:mysql://127.0.0.1:3306/test');
>> curs = exec(conn,sqlCmd);
>> curs.Message
ans =
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'select iid.id,t1.val,t2.val from iid left join t1 on iid.id=t1.id left join t2 o' at line 1
>> curs = exec(conn,'select * from t1');
>> curs = fetch(curs);
>> curs.Data
ans =
1 100
2 200
>> sqlCmd
I'm a pure newbie of SQL, and I have no idea for this error message.
Any help would be appreciated.
It would appear that Matlab treats each string in your sqlCmd matrix as a separate SQL statment. As you are breaking up the queries into string portions this will not work, because each not every portion is a valid standalone SQL statement. As the comment above suggests, you may need to search for a setting that allows this. Alternatively you could try to rewrite your SQL into a single string just like you did with mysql:
sqlCmd = 'create or replace view iid as select id from t1 union select id from t2;select iid.id,t1.val,t2.val from iid left join t1 on iid.id=t1.id left join t2 on iid.id=t2.id;';
curs = exec(conn,sqlCmd);
This should at least run your query without error. If you have not done so already, take a look at the mathworks documentation for exec http://www.mathworks.co.uk/help/toolbox/database/ug/exec.html

Why is this MySQL JOIN statement returning more results?

I have two (characteristic_list and measure_list) tables that are related to each other by a column called 'm_id'. I want to retrieve records using filters (columns from characteristic_list) within a date range (columns from measure_list). When I gave the following SQL using INNER JOIN, it takes a while to retrieve the record. What am I doing wrong?
mysql> explain select c.power_set_point, m.value, m.uut_id, m.m_id, m.measurement_status, m.step_name from measure_list as m INNER JOIN characteristic_lis
t as c ON (m.m_id=c.m_id) WHERE (m.sequence_end_time BETWEEN '2010-06-18' AND '2010-06-20');
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
| 1 | SIMPLE | c | ALL | NULL | NULL | NULL | NULL | 82952 | |
| 1 | SIMPLE | m | ALL | NULL | NULL | NULL | NULL | 85321 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+-------+-------------+
2 rows in set (0.00 sec)
mysql> select count(*) from measure_list;
+----------+
| count(*) |
+----------+
| 83635 |
+----------+
1 row in set (0.18 sec)
mysql> select count(*) from characteristic_list;
+----------+
| count(*) |
+----------+
| 83635 |
+----------+
1 row in set (0.10 sec)
The reason this query takes a while to execute is because it has to scan the entire table. You never want to see "ALL" as the type of the query. To speed things up, you need to make smart decisions about what to index.
See the following documents at the MySQL site:
http://dev.mysql.com/doc/refman/5.1/en/mysql-indexes.html
http://dev.mysql.com/doc/refman/5.1/en/using-explain.html
As an add-on to the previous answer by Dan, you should consider indexing the join columns and the where columns. In this case, that means the m_id cols in both tables and the sequence_end_time in the measure_list table. They are small enough that you could add an index, run explain plan and time it, then change the index and compare. Should be relatively quick to solve.