Compairing two strings in MYSQL - mysql

I have a sequence of 20 numbers from 0 to 2, I want to compare this string with other sequences saved in my database, the problem is that the lenght of the strings saved on the database fluctuates.Also the comparison needs to be done from the end to the start.
Example of what I want:
20 digits string:
'1,1,2,1,2,1,0,1,2,1,2,1,0,1,2,1,1,1,2,1'
couple of strings saved in the database:
1 - '1,1,2,1'
2 - '2,1,2,2,2,2'
3 - '2,1'
4 - '1,1,2,1,2,1'
In this case the query would return the 1 and 3 only

create table mytable ( s varchar(60) );
insert into mytable values
('1,1,2,1'),
('2,1,2,2,2,2'),
('2,1'),
('1,1,2,1,2,1');
set #x = '1,1,2,1,2,1,0,1,2,1,2,1,0,1,2,1,1,1,2,1';
select s from mytable
where right(#x, length(s)) = s;
Output:
s
1,1,2,1
2,1
Fiddle: https://www.db-fiddle.com/f/r5m2hPbnmUu5VQfYvMVtir/0

You could use a LIKE trick here. For example, to check for the first string 1,1,2,1:
SELECT *
FROM yourTable
WHERE ',1,1,2,1,2,1,0,1,2,1,2,1,0,1,2,1,1,1,2,1,' LIKE '%,1,1,2,1,%';

Related

How to write sql query where the WHERE clause uses a substring casted to a long?

In a table called "accounts" there is an account id that is a 13 character long string, where the first 8 digits are the user id who owns that account. How do I query the database with an integer and check the first 8 characters only?
I was trying to do something like this:
SELECT * FROM networthr.accounts WHERE CAST(SUBSTRING(account_id, 0, 8) as long) = 1;
But it won't even let me run this query.
There are 2 problems with your query:
1) The 2nd argument of SUBSTRING() should be 1 (the index is 1 based not 0 based)
2) You should cast to the data type UNSIGNED
SELECT * FROM networthr.accounts WHERE CAST(SUBSTRING(account_id, 1, 8) as unsigned ) = 1;
This looks like a bad design. However - If the account_id is zero padded like "00000001ABCDE" and you have an index on it, an efficient way would be
SELECT *
FROM networthr.accounts
WHERE account_id LIKE CONCAT(LPAD(?, 8, 0), '%')
Replace ? with the user_id or use it as a prepared statement and bind user_id as parameter.
In case of user_id = 1 it's the same as
WHERE account_id LIKE '00000001%'
You can use implicit conversion:
WHERE LEFT(account_id, 8) + 0 = 1
However, you should really be comparing strings to string.

MySQL strange behavior when comparing comma-separated string with number

I am experiencing some weird behavior with MySQL. Basically I have a table like this:
ID string
1 14
2 10,14,25
Why does this query pull id 2?
SELECT * FROM exampletable where string = 10
Surely it should be looking for an exact match, because this only pulls id 1:
SELECT * FROM exampletable where string = 14
I am aware of FIND_IN_SET, I just find it odd that the first query even pulls anything. Its behaving like this query:
SELECT * FROM exampletable where string LIKE '10%'
When you compare a numeric and a string value, MySQL will attempt to convert the string to number and match. Number like strings are also parsed. This we have:
SELECT '10,14,25' = 1 -- 0
SELECT '10,14,25' = 10 -- 1
SELECT 'FOOBAR' = 1 -- 0
SELECT 'FOOBAR' = 0 -- 1
SELECT '123.456' = 123 -- 0
SELECT '123.456FOOBAR' = 123.456 -- 1
The behavior is documented here (in your example it is the last rule):
...
If one of the arguments is a decimal value, comparison depends on the
other argument. The arguments are compared as decimal values if the
other argument is a decimal or integer value, or as floating-point
values if the other argument is a floating-point value.
In all other cases, the arguments are compared as floating-point
(real) numbers.

MySQL match area code only when given the full number

I have a database that lists a few area codes, area code + office codes and some whole numbers and a action. I want it to return a result by the digits given but I am not sure how to accomplish it. I have some MySQL knowledge but its not very deep.
Here is a example:
match | action
_____________________
234 | goto 1
333743 | goto 2
8005551212| goto 3
234843 | goto 4
I need to query the database with a full 10 digit number -
query 8005551212 gives "goto 3"
query 2345551212 gives "goto 1"
query 3337431212 gives "goto 2"
query 2348431212 gives "goto 4"
This would be similar to the LIKE selection, but I need to match against the database value instead of the query value. Matching the full number is easy,
SELECT * FROM database WHERE `match` = 8005551212;
First the number to query will always be 10 digits, so I am not sure how to format the SELECT statement to differentiate the match of 234XXXXXXX and 234843XXXX, as I can only have one match return. Basically if it does not match the 10 digits, then it checks 6 digits, then it will check the 3 digits.
I hope this makes sense, I do not have any other way to format the number and it has to be accomplished with just a single SQL query and return over a ODCB connection in Asterisk.
Try this
SELECT match, action FROM mytable WHERE '8005551212' like concat(match,'%')
The issue is that you will get two rows in one case .. given your data..
SELECT action
FROM mytable
WHERE '8005551212' like concat(match,'%')
order by length(match) desc limit 1
That should get the row that had the most digits matched..
try this:
SELECT * FROM (
SELECT 3 AS score,r.* FROM mytable r WHERE match LIKE CONCAT(SUBSTRING('1234567890',1,3),'%')
UNION ALL
SELECT 6 AS score,r.* FROM mytable r WHERE match LIKE CONCAT(SUBSTRING('1234567890',1,6),'%')
UNION ALL
SELECT 10 AS score,r.* FROM mytable r WHERE match LIKE CONCAT(SUBSTRING('1234567890',1,10),'%')
) AS tmp
ORDER BY score DESC
LIMIT 1;
What ended up working -
SELECT `function`,`destination`
FROM reroute
WHERE `group` = '${ARG2}'
AND `name` = 0
AND '${ARG1}' LIKE concat(`match`,'%')
ORDER BY length(`match`) DESC LIMIT 1

Populate column with number of substrings in another column

I have two tables "A" and "B". Table "A" has two columns "Body" and "Number." The column "Number" is empty, the purpose is to populate it.
Table A: Body / Number
ABABCDEF /
IJKLMNOP /
QRSTUVWKYZ /
Table "B" only has one column:
Table B: Values
AB
CD
QR
Here is what I am looking for as a result:
ABABCDEF / 3
IJKLMNOP / 0
QRSTUVWKYZ / 1
In other words, I want to create a query that looks up, for each string in the "Body" column, how many times the substrings in the "Values" column appear.
How would you advise me to do that?
Here's the finished query; explanation will follow:
SELECT
Body,
SUM(
CASE WHEN Value IS NULL THEN 0
ELSE (LENGTH(Body) - LENGTH(REPLACE(Body, Value, ''))) / LENGTH(Value)
END
) AS Val
FROM (
SELECT TableA.Body, TableB.Value
FROM TableA
LEFT JOIN TableB ON INSTR(TableA.Body, TableB.Value) > 0
) CharMatch
GROUP BY Body
There's a SQL Fiddle here.
Now for the explanation...
The inner query matches TableA strings with TableB substrings:
SELECT TableA.Body, TableB.Value
FROM TableA
LEFT JOIN TableB ON INSTR(TableA.Body, TableB.Value) > 0
Its results are:
BODY VALUE
-------------------- -----
ABABCDEF AB
ABABCDEF CD
IJKLMNOP
QRSTUVWKYZ QR
If you just count these you'll only get a value of 2 for the ABABCDEF string because it just looks for the existence of the substrings and doesn't take into consideration that AB occurs twice.
MySQL doesn't appear to have an OCCURS type function, so to count the occurrences I used the workaround of comparing the length of the string to its length with the target string removed, divided by the length of the target string. Here's an explanation:
REPLACE('ABABCDEF', 'AB', '') ==> 'CDEF'
LENGTH('ABABCDEF') ==> 8
LENGTH('CDEF') ==> 4
So the length of the string with all AB occurrences removed is 8 - 4, or 4. Divide the 4 by 2 (LENGTH('AB')) to get the number of AB occurrences: 2
String IJKLMNOP will mess this up. It doesn't have any of the target values so there's a divide by zero risk. The CASE inside the SUM protects against this.
You want an update query:
update A
set cnt = (select sum((length(a.body) - length(replace(a.body, b.value, '')) / length(b.value))
from b
)
This uses a little trick for counting the number of occurrence of b.value in a given string. It replaces each occurrence with an empty string and counts the difference in length of the strings. This is divided by the length of the string being replaced.
If you just wanted the number of matches (so the first value would be "2" instead of "3"):
update A
set cnt = (select count(*)
from b
where a.body like concat('%', b.value, '%')
)

How to return all matches in mysql where value occurs in string at position n?

Im looking to run a query in phpmyadmin (mysql) that wil check a table for a specific value at a specific postion in a string, i'm new to mysql and this is what i've tried but there's a syntax issue. I'm looking to find the value "1" at position 5 and display all those users that possess this.
SELECT*
FROM`user`
WHERE`options`LOCATE(`options`,1,5)
LIMIT 0 , 30
regards,
Silo
Locate is for finding a value ANYWHERE in a string. You want a specific location only, so use substr() instead:
SELECT *
FROM user
WHERE substr(options, 5, 1) = '1'
You could try
SELECT*
FROM`user`
WHERE options LIKE '____1%'
LIMIT 0 , 30
Another ;)
SELECT *
FROM user
WHERE instr(options, '1') = 5
Duh .. Well won't work since it only returns the first occurnace :$ But CHECK the reference,
SQLFIDDLE using Locate()
Sample data:
COL1 COL2
G11 112
G11-1 0
G11-2 2
G12-2 111
Query1:
-- to check on varchar columns
SELECT *
FROM tablex
where locate('1',col1,5)
;
Results on varchar:
COL1 COL2
G11-1 0
Query 2:
-- to check on int columns
SELECT *
FROM tablex
where locate(1,col2,2)
;
Results on int:
COL1 COL2
G11 112
G12-2 111