How to convert select statement result to JSONARRAY and update another table - mysql

I want to convert select result to JSON and write it to another table:
update patrol_patrol a, position_user b
set a.route = json_array(select coordinate from b )
where a.id = 1;
and get error:
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 coordinate from b ) where a.id = 1' at line 2
select route from patrol_patrol;
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| route |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| ["112.58006496213066,22.311484443420195"] |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set
select coordinate from position_user;
+---------------------------------------+
| coordinate |
+---------------------------------------+
| 112.701036,22.738611 |
| 112.701036,22.738632 |
| 112.701036,22.738632 |
| 112.701036,22.738652
position_user.coordinate should be ["112.701036,22.738611", "112.701036,22.738632", "112.701036,22.738652", ....] after update

Since you're only updating the patrol_patrol table, you should only include that in the first part of your update statement. To get what you're looking for, I recommend using the JSON_ARRAYAGG function, which will combine your results into one array, which can then be used to assign the result to a.route:
UPDATE patrol_patrol a
SET a.route = (SELECT JSON_ARRAYAGG(coordinate) FROM position_user)
WHERE a.id = 1;
A dbfiddle can be found here demonstrating this approach.

Related

Using Self-Join to find differences between rows

I have tried finding a solution to this question, but everything I've found has either asked a slightly different question or hasn't had an adequate answer. I have a table with the following setup:
fullvna
+--------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+----------------+
| startdate | date | YES | | NULL | |
| starttime | time | YES | | NULL | |
| id | int(11) | NO | PRI | NULL | auto_increment |
+--------------+-------------+------+-----+---------+----------------+
I want to find the time difference between each pair of consecutive lines, so the starttime of id=1 minus the starttime of id=2 (the table is ordered in reverse chronological order). I based my query off of what I found here: http://www.mysqltutorial.org/mysql-tips/mysql-compare-calculate-difference-successive-rows/
create table difference as SELECT
one.id,
     one.starttime,
     two.starttime,
    (one.starttime - two.starttime) AS diff
FROM
     fullvna one
        INNER JOIN
    fullvna two ON two.id = one.id + 1;
I'm receiving the following printout, and am not sure what it means or what I'm doing wrong:
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 '  one.starttime,
    two.starttime,
    (one.starttime - two.starttime' at line 3
You have hidden characters that are displayed as spaces, but they're not and they're causing the error. Copy the query from my answer. And as Juan suggested, it is recommended to use the TIMEDIFF() function instead of subtracting them:
CREATE TABLE difference AS
SELECT one.id,
one.starttime AS starttime,
two.starttime AS endtime,
TIMEDIFF(one.starttime, two.starttime) AS diff
FROM fullvna one
INNER JOIN fullvna two ON two.id = one.id + 1;
EDIT As xQbert mentioned, you need to use different names for the starttime column, so I corrected the query above accordingly.
Don't use alias one as it's a keyword pick a different one
alias startime as two columns with same name in a create table will not work.
timediff (as others mentioned in comments)
.
CREATE TABLE difference as
SELECT a1.id
, a1.starttime as OneStartTime
, a2.starttime as TwoStartTime
, TIMEDIFF(a1.starttime, a2.starttime) AS diff
FROM fullvna a1
INNER JOIN fullvna a2
ON a2.id = a1.id + 1;

MySQL query to identify near duplicate matches with specific pattern, update child table

Due to a badly parsed .csv LOAD DATA INFILE routine, I now have rows in the unique host.name field with nearly duplicate values, differing only that one set leads with a carriage return (0A). host.id in all the correct rows is <100 and conversely host.id in all incorrect rows is >100.
That's simple to correct of course, but I also now have incorrectly linked data in host_metric from updates that joined the incorrect near duplicates with host.id = host_metric.host_id
So, I need to update host_metric.host_id with the correct host.id value first. I was thinking of solving by joining the host table on itself by making the nearly duplicate host.name duplicate, and updating host_metric.host_id with a.id, but I'm getting tangled up.
UPDATE host_metric c
SET c.host_id = (SELECT a.id
FROM host a
INNER JOIN host b ON concat("0A", hex(a.name)) = hex(b.name)
WHERE a.id <> b.id
AND a.id < '100'
AND b.id > '100')
INNER JOIN host d ON c.host_id = d.id;
How can I correctly phrase this query?
EDIT: Here's some sample data:
Here's some sample near duplicate rows from host table (146 is incorrect):
MySQL [vmr]> select id, name from host where name like "%d60server10%";
+-----+--------------------------+
| id | name |
+-----+--------------------------+
| 1 | d60server10.domain |
| 146 |
d60server10.domain |
+-----+--------------------------+
Here's a correct entry in host_metric with the correct host_id:
MySQL [vmr]> select * from host_metric where host_id='1' limit 1;
+---------+-----------+---------------------+-------+
| host_id | metric_id | metric_ts | value |
+---------+-----------+---------------------+-------+
| 1 | 1 | 2016-06-08 06:30:00 | 1.23 |
+---------+-----------+---------------------+-------+
Here's an incorrect entry in host_metric, linked from almost-duplicate row in host:
MySQL [vmr]> select * from host_metric where host_id='146' limit 1;
+---------+-----------+---------------------+-------+
| host_id | metric_id | metric_ts | value |
+---------+-----------+---------------------+-------+
| 146 | 1 | 2016-06-07 06:30:00 | 0.57 |
+---------+-----------+---------------------+-------+
So in this example data, I need to update all rows in host_metric where `host_id = 146' to '1'.
In case anyone runs across anything similar, I was able to repair this (I believe) by breaking it down a little bit and using a temporary table.
Beforehand I ran: SELECT host_id,count(host_id) FROM host_metric GROUP BY host_id; to get a total count of each id. After step #5 below, I re-ran this and the correct ID counts reflected the addition of the merged incorrect ids.
Create temp table
CREATE TABLE host_tmp LIKE host;
Copy over the problematic near duplicate rows to temp table from original:
INSERT INTO host_tmp SELECT * FROM HOST WHERE id > '100';
Remove hidden characters in name field in host_tmp so we can join with it:
UPDATE host_tmp SET name = replace(name,'\r','');
UPDATE host_tmp SET name = replace(name,'\n','');
Add a column to the temp table to match the original (correct) ids:
ALTER TABLE host_tmp ADD ido int(4);
Populate the original (correct) ids from host so we have an index:
UPDATE host_tmp t
INNER JOIN host h ON t.name = h.name
SET t.ido = h.id
WHERE t.id > 100;
Update the host_metric (child) table so to correct the host_ids:
UPDATE host_metric m
INNER JOIN host_tmp t ON t.id = m.host_id
SET m.host_id = t.ido
WHERE m.host_id > '100';
Remove the (incorrect) almost duplicate rows from host:
DELETE FROM host where id > '100';
Finally, remove the temporary table:
DROP table host_tmp;

SET a variable in SELECT statement - MySQL

I'm using this code which has an error:
SET #rejects = '';
SELECT *
FROM list
WHERE maker = 1
AND by_ids IN ('10','11')
AND country LIKE '%I%'
AND (
src IS NULL
|| src NOT IN (#rejects)
AND checkSrc(src) = 'yes'
AND SET #rejects = CONCAT(#rejects,',',src)
);
What's causing the issue?
The issue is that you cannot mix select and set in one statement, there'll surely be syntax error:
select*from t where 1 and set#a=1;
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 'set#a=1' at line 1
If you want to do set within select, use the colon equals syntax. Change this:
select*from t where 1 and set#a=1;
into:
select*,#a:=1 from t where 1;
Here's how you update the variable upon each row:
create table t(id int); insert t values(1),(2),(3);
set#a=0;
select#a:=id from t;
+--------+
| #a:=id |
+--------+
| 1 |
| 2 |
| 3 |
+--------+
And you can even do concat:
set#a='0';
select #a:=concat(#a,',',id)from t;
+-----------------------+
| #a:=concat(#a,',',id) |
+-----------------------+
| 0,1 |
| 0,1,2 |
| 0,1,2,3 |
+-----------------------+
Or concat without the leading 0:
set#a='';
select #a:=concat(#a,if(#a='','',','),id)from t;
+------------------------------------+
| #a:=concat(#a,if(#a='','',','),id) |
+------------------------------------+
| 1 |
| 1,2 |
| 1,2,3 |
+------------------------------------+
However, the manual explicitly states that this is dangerous:
...you should never assign a value to a user variable and read the
value within the same statement...
...you might get the results you expect, but this is not
guaranteed.
...the order of evaluation for expressions involving user variables is
undefined.
This has also been mentioned on Xaprb.
Lastly, if you're doing quirky things like assigning differing value types to the variable and etc, checkout the manual to be sure you understand the intricate mechanisms.
Then you might write your query like this.
SET #rejects = '';
SELECT #rejects = CONCAT(#rejects,',',src) FROM list WHERE maker = 1 AND by_ids IN ('10','11') AND country LIKE '%I%' AND
(src IS NULL OR src NOT IN (#rejects) AND checkSrc(src) = 'yes');
SELECT #rejects;

MySQL - Merge two join results

I need help with a raw SQL query which gets a value based on another value.
I have the following raw SQL query.
SELECT pmPropDef.id, pmPropDef.name, pmPropDef.units, pmPropShort.str, pmPropLong.str
FROM pmProp INNER JOIN pmPropDef ON pmProp.propid=pmPropDef.id AND pmPropDef.name = 'Area'
LEFT JOIN pmPropShort ON sid=pmProp.value
LEFT JOIN pmPropLong ON lid=-pmProp.value
WHERE pmProp.ownertype='variant' AND pmPropDef.id = pmProp.propid;
And this results in the following:
+----+------+-------+------+------+
| id | name | units | str | str |
+----+------+-------+------+------+
| 14 | Area | mm2 | 1.1 | NULL |
+----+------+-------+------+------+
The problem that I am getting both pmPropShort.str and pmPropLong.str and I should be betting one or the the other. What I really want is a single str value? How do I re-write this query to meet my needs?
You can use COALESCE which returns the first non-NULL argument. eg.
COALESCE(pmPropShort.str, pmPropLong.str)
Do you have an obvious priority?
example if long is priority
SELECT pmPropDef.id, pmPropDef.name, pmPropDef.units,
IF(pmPropLong.str IS NOT NULL,pmPropLong.str,pmPropShort.str) as str
FROM ...rest of your query

Why am I getting this syntax-error while trying to update a attribute using mysql-query?

I am trying to update 'pwd' column of 'Goal' table using following mysql query but sad thing is it gives error. mysql query:
UPDATE Goal
SET pwd = (SELECT MD5(CONCAT(ID, LEFT(phone,3), '$='))
FROM Esubmission);
error:
1064 - 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 'FROM Esubmission)' at line 1
My tables are like below;
Esubmission
ID | pnone | email |
--------------------------------------------
20378 | 00000000000 | someone#gmail.com|
20379 | 00000000000 | someone#gmail.com|
20380 | 00000000000 | someone#gmail.com|
Goal
usr | pwd | time|
--------------------
20378 | |12:09|
20379 | |15:29|
20380 | |15:47|
Hmm.... I'm thinking that you really want to set the password for each user (I think), in which case you'll need to have a join for the update, and that way you can eliminate your multiple values you are selecting.. because the way you have it, you're updating all the values in the Goal table for pwd to the same value... the way below, you update each users pwd to be based on the row joined with the ID. Assuming you have one row for each usr in the esubmission table, this should work:
UPDATE Goal
SET pwd = MD5(CONCAT(ID, LEFT(e.phone,3), '$='))
FROM Goal g, Esubmission e
where e.ID = g.usr
I tested it here and worked fine. MySQL 5.1.37