I'm running into a problem, I have the following line in my query
CONCAT('',
(SELECT GROUP_CONCAT(DISTINCT trips_loads_rel.load_id,'') AS x
FROM `trips_loads_rel` WHERE trips_loads_rel.trip_id = trips.Id)
) AS loads
It shows something like 8,10,27 (ie, numeric IDs), some Ids from trips_loads_rel table. It works ok. However, how can I use that output to pull matching records from other table? I mean, the line shows me all ids ok, but I need to query other table with these to pull related records. Actually I don't need these IDs, I need their matching records...
try this:
SELECT * FROM <other_table> WHERE <other_table>.load_id IN(CONCAT('',
(SELECT GROUP_CONCAT(DISTINCT trips_loads_rel.load_id,'') AS x
FROM `trips_loads_rel` WHERE trips_loads_rel.trip_id = trips.Id)
) AS loads)
It looks like it's a part of a query, not an entire one, so hard to show exact syntax, but if you want to use the values to find other rows, just don't group concat them to begin with.
Instead just use them directly doing something like;
SELECT * FROM `other_table` WHERE `other_table`.`load_id` IN
(SELECT `load_id` FROM `trips_loads_rel` WHERE `trip_id` = `trips`.`Id`)
You can use FIND_IN_SET(col, 'csv as string') function to get the desired results.
Example:
mysql> select find_in_set( 2, '11,12,13,14,15,2' );
+--------------------------------------+
| find_in_set( 2, '11,12,13,14,15,2' ) |
+--------------------------------------+
| 6 |
+--------------------------------------+
1 row in set (0.00 sec)
mysql> select find_in_set( 2, '2,11,12,13,14,15,2' );
+----------------------------------------+
| find_in_set( 2, '2,11,12,13,14,15,2' ) |
+----------------------------------------+
| 1 |
+----------------------------------------+
1 row in set (0.00 sec)
mysql> Select FIND_IN_SET( 6, '1,12,3,14,5,16,7,18,9,0,2,13,4,15,6,17,8' );
+--------------------------------------------------------------+
| FIND_IN_SET( 6, '1,12,3,14,5,16,7,18,9,0,2,13,4,15,6,17,8' ) |
+--------------------------------------------------------------+
| 15 |
+--------------------------------------------------------------+
1 row in set (0.00 sec)
mysql>
For your query you can pass the concatenated output '8,10,27' to compare with other_table's column.
Select find_in_set( other_table.col_name, '8,10,27' );
Refer To:
MySQL String Functions: FIND_IN_SET()
Related
I am running the following query on my wordpress website
$error = $wpdb->update( $table_name,
array( 'value' => $update_value ),
array( 'lead_id' => $lead_id,
'field_number' => 31.3 ),
array( '%s' ),
array( '%d', '%f' )
);
It is intended to update gravity form entries after the user has initially submitted the form. This query runs fine for 24 fields but returns 0 for 2.
I have so far tried the following troubleshooting steps:
Storing the result as $error and running var_dump($error); after the query, it returns 0.
Running var_dump( $wpdb->last_query ); immediately after the query to copy/paste the resulting SQL string into phpMyAdmin, which also reports 0 rows affected.
Manually selecting the row in phpMyAdmin using:
SELECT * FROM `table_name` WHERE `field_number` = 31.3
Which also returns no rows. However, I know that there are rows which match as I can se them in the table.
Manually selecting another field which updates as expected using the same query as above - this worked fine.
Changed the $where_format from float to string. No resulting change. Upon checking the db fields, the field_number field is stored as a float.
Used $wpdb->prepare to run a prepared query. Still no movement.
Prepare statement as follows:
$error = $wpdb->query(
$wpdb->prepare(
"
UPDATE %s
SET value = %s
WHERE lead_id = %d AND field_number = %f
",
$table_name, $update_value, $lead_id, 31.3
)
);
Which, when var_dumped gives the following result:
string '
UPDATE prefix_rg_lead_detail
SET `value` = 'a:3:{i:0;s:9:\"Liverpool\";i:1;s:10:\"Manchester\";i:2;s:5:\"Leeds\";}'
WHERE `lead_id` = 4 AND `field_number` = 31.300000
' (length=188)
I'm at my wits end now as I've tried everything I can possibly think of and still cant get 2 fields to update.
Your final problem is indeed with the FLOAT type. It is an imprecise value, which is leading you to your problem. Although the database is showing the value 31.3 it most likely internally in the database is something like 31.30000000000001 which is why the where condition is not working. Take a look at the documentation here: Problems with Floating-Point Values.
So down the road lets go to the tests:
create table test (
n float
);
insert into test values (31.3);
mysql> select * from test;
+------+
| n |
+------+
| 31.3 |
+------+
1 row in set (0.17 sec)
Running a select statement on it with that value 31.3 will evaluate to nothing:
mysql> select * from test where n=31.3;
Empty set (0.00 sec)
There are a few ways you can solve it without changing the column type:
1- Using the ROUND(field,number_of_decimals) function
mysql> select * from test where round(n,2)=31.3;
+------+
| n |
+------+
| 31.3 |
+------+
1 row in set (0.00 sec)
2- Casting it as DECIMAL type
mysql> select * from test where cast(n as decimal(5,2))=31.3;
+------+
| n |
+------+
| 31.3 |
+------+
1 row in set (0.00 sec)
So in order to your update to work with this data you have to use one of those options in your update command like:
$wpdb->query( $wpdb->prepare("UPDATE %s
SET value = %s
WHERE lead_id = %d
AND round(field_number,2) = %f ",
$table_name,
$update_value,
$lead_id,
31.3 )
);
My recommendation is that you change the field type. AFAIK there is no situation where your plugin may break as of this change. What it may happens is a rounding value like you try to insert a value like 31.696 in a Decimal field of (6,2) it will became 31.67. Also the difference is that the value of the field will be formatted as the decimals number you chose so 31.3 will start to apear as 31.30 You can change it as:
alter table yourTableName modify field_name DECIMAL(6,2);
Here are some test on that explanation:
mysql> alter table test modify column n decimal(10,2);
Query OK, 1 row affected, 1 warning (0.90 sec)
Records: 1 Duplicates: 0 Warnings: 1
mysql> select * from test;
+-------+
| n |
+-------+
| 31.30 |
+-------+
1 row in set (0.00 sec)
mysql> select * from test where n=31.3;
+-------+
| n |
+-------+
| 31.30 |
+-------+
1 row in set (0.00 sec)
And to show the rounding:
mysql> insert into test values (31.696);
Query OK, 1 row affected, 1 warning (0.01 sec)
mysql> select * from test;
+-------+
| n |
+-------+
| 31.30 |
| 31.67 |
+-------+
2 rows in set (0.01 sec)
I have a SQL query that's fetching a result like:
[{"id":89,"sender_id":2,"reciever_id":1,"message":"no reply","deleted_at":null,"created_at":"2017-04-04 17:01:20","updated_at":"2017-04-04 17:01:20"},
{"id":88,"sender_id":1,"reciever_id":2,"message":"hiiiii","deleted_at":null,"created_at":"2017-04-04 16:59:47","updated_at":"2017-04-04 16:59:47"},
{"id":87,"sender_id":5,"reciever_id":1,"message":"hiiiii","deleted_at":null,"created_at":"2017-04-04 16:59:43","updated_at":"2017-04-04 16:59:43"},
{"id":86,"sender_id":1,"reciever_id":5,"message":"hiiii","deleted_at":null,"created_at":"2017-04-04 16:59:38","updated_at":"2017-04-04 16:59:38"},
{"id":85,"sender_id":1,"reciever_id":5,"message":"hiii vRUN\n","deleted_at":null,"created_at":"2017-04-04 16:10:51","updated_at":"2017-04-04 16:10:51"}]
But I want only unique combinations of sender_id and reciever_id. I need only 2 rows out of 5 because only 2 rows have unique combination. Like this:
[{"id":89,"sender_id":2,"reciever_id":1,"message":"no reply","deleted_at":null,"created_at":"2017-04-04 17:01:20","updated_at":"2017-04-04 17:01:20"},
{"id":87,"sender_id":5,"reciever_id":1,"message":"hiiiii","deleted_at":null,"created_at":"2017-04-04 16:59:43","updated_at":"2017-04-04 16:59:43"},
How can I achieve that?
add a GROUP BY like this
SELECT *
FROM yourTable
GROUP BY SUBSTRING_INDEX(SUBSTRING_INDEX( ,',',3),':',-1)
sample
mysql> SELECT SUBSTRING_INDEX(SUBSTRING_INDEX('[{"id":89,"sender_id":2,"reciever_id":1,"message":"no reply","deleted_at":null,"created_at":"2017-04-04 17:01:20","updated_at":"2017-04-04 17:01:20"},' ,',',3),':',-1) as result;
+--------+
| result |
+--------+
| 1 |
+--------+
1 row in set (0,00 sec)
mysql>
Suppose I have a table named "t1" which contains a column named "ID" which has the following records
abcde=1=2
qwert=3
hhhhj=9
zxcv=5=8
How can I extract the records that contain only 1 "=" sign by using REGEXP in MySQL?
I've tried
SELECT * FROM t1 WHERE ID REGEXP '\\w*=\\w*=\\w*'; -- returns no records
SELECT * FROM t1 WHERE ID REGEXP '\\w*=\\w*'; -- returns all 4 records
I expected the first query to return the records which contains 2 "=", and the second query to return the records which contains only 1 "=".
What's wrong with my queries?
A pretty simple solution without REGEXP would be
select * from table
where
length(ID) - length(replace(ID,'=','')) = 1 ;
Some test cases
mysql> select length('qwert=3') - length(replace('qwert=3','=','')) as diff;
+------+
| diff |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
mysql> select length('zxcv=5=8') - length(replace('zxcv=5=8','=','')) as diff;
+------+
| diff |
+------+
| 2 |
+------+
1 row in set (0.00 sec)
SELECT * FROM t1 WHERE ID REGEXP '^[^=]*=[^=]*$';
Guess this should do it.See fiddle http://www.sqlfiddle.com/#!9/b2ead/2/0
I have to get last 5 numbers using mysql.
My values are like YOT-A78514,LOP-C4521 ...
I have to get only last five char . How can I do this in query?
You can do this with RIGHT(str,len) function. Returns the rightmost len characters from the string str,
Like below:
SELECT RIGHT(columnname,5) as yourvalue FROM tablename
"Right"-function is the way to, using the substring may lead to an problem that is not so easy to notice:
mysql> select right('hello', 6);
+-------------------+
| right('hello', 6) |
+-------------------+
| hello |
+-------------------+
1 row in set (0.00 sec)
mysql> select substring('hello', -6);
+------------------------+
| substring('hello', -6) |
+------------------------+
| |
+------------------------+
1 row in set (0.00 sec)
But if you don't try to go past the start of the string, then substring of course works fine:
mysql> select substring('hello', -5);
+------------------------+
| substring('hello', -5) |
+------------------------+
| hello |
+------------------------+
1 row in set (0.00 sec)
Right is a good choice but you can also use substring like this-
SELECT Substring(columnname,-5) as value FROM table_name
SELECT row_id
FROM column_name
WHERE column_value LIKE '%12345';
This will return the "row_id" when "12345" is found to be the tailing suffix of the "column_value" within the "column_name".
And if you want to get a dinamic number of right characters after a character:
SELECT TRIM(
RIGHT(
database.table.field,
(LENGTH(database.table.field) - LOCATE('-',database.table.field))
)
)
FROM database.table;
SELECT SUBSTR('Stringname', -5) AS Extractstring;
Suppose I have a 2 column table like this:
| user_id | int(11) | NO | UNI | NULL | |
| utm | point | NO | MUL | NULL | |
As you can see, it's very simple. utm is a Point data-type. I insert it like this:
INSERT INTO mytable(user_id, utm) VALUES(1, PointFromWKB(point(50, 50)));
Then, I create a Spatial index.
ALTER TABLE mytable ...add spatial index on(utm) or something. (forgot)
Alright, everything is good. Now , I want to select * where distance < 99999.
But it doesn't work!
//This is supposed to select all where the distance is less than 99999999.
set #mypoint = PointFromWKB(point(20,20))
select * from mytable where GLength(LineString(utm, #mypoint)) < 9999999;
Empty set (0.00 sec)
select * from mytable where GLength(LineStringFromWKB(LineString(utm, #mypoint))) < 9999;
Empty set (0.00 sec)
By the way, I have tried to INSERT INTO without the PointFromWKB...and it didn't work...that's why someone suggested that PointFromWKB to me.
Solved. This is what I did:
where GLength(LineStringFromWKB(LineString(asbinary(utm), asbinary(#mypoint)))) < 9999999999999;
You can also do it this way. Not sure if it's faster or not.
select * from mytable where glength(geomfromtext(concat('linestring(', x(utm), ' ', y(utm), ',20 20', ')'))) < 99999999
As far as I know, u have to try this way-
select * from mytable
where
(
GLength(
LineStringFromWKB(
LineString(
geoPoint,
GeomFromText('POINT(51.5177 -0.0968)')
)
)
)
) < 99999999
More in this answer.
If you are considering points as longitude and latitude values on earth you can use ST_Distance_Sphere function to calculate distance between 2 points.
mysql> SET #p1 = ST_GeomFromText('POINT(3.13 52.5)');
Query OK, 0 rows affected (0.00 sec)
mysql> SET #p2 = ST_GeomFromText('POINT(100.4 27.8)');
Query OK, 0 rows affected (0.00 sec)
mysql>
mysql> SELECT ST_Distance_Sphere(#p1, #p2) AS distance;
+-------------------+
| distance |
+-------------------+
| 8053869.706740822 |
+-------------------+
1 row in set (0.05 sec)
Value you get is from meters. And also you can give a preferred radius as an optional argument to the function ST_Distance_Sphere to calculate distance.
You can find more details on this from official documentation.
https://dev.mysql.com/doc/refman/5.7/en/spatial-convenience-functions.html