Select rows which a string starts with - mysql

I have a string /path/to/project/subdirectory/ and need to find a row where path is /path/to/project/.
How can I find rows where my string starts with path?
It would be the opposite of:
SELECT * FROM projects WHERE path LIKE "/path/to/%"
Because I have too many characters, not too few.
Both of these return zero rows:
SELECT * FROM projects WHERE path LIKE "/path/to/project/subdirectory/%"
SELECT * FROM projects WHERE "/path/to/project/subdirectory/" LIKE (path+"%")

You were close with your second attempt, but MySQL uses CONCAT() to concatenate strings, not +.
SELECT *
FROM projects
WHERE "/path/to/project/subdirectory/" LIKE CONCAT(path, '%')
You can also use
WHERE LOCATE(path, "/path/to/project/subdirectory/") = 1

Related

How to find variable pattern in MySql with Regex?

I am trying to pull a product code from a long set of string formatted like a URL address. The pattern is always 3 letters followed by 3 or 4 numbers (ex. ???### or ???####). I have tried using REGEXP and LIKE syntax, but my results are off for both/I am not sure which operators to use.
The first select statement is close to trimming the URL to show just the code, but oftentimes will show a random string of numbers it may find in the URL string.
The second select statement is more rudimentary, but I am unsure which operators to use.
Which would be the quickest solution?
SELECT columnName, SUBSTR(columnName, LOCATE(columnName REGEXP "[^=\-][a-zA-Z]{3}[\d]{3,4}", columnName), LENGTH(columnName) - LOCATE(columnName REGEXP "[^=\-][a-zA-Z]{3}[\d]{3,4}", REVERSE(columnName))) AS extractedData FROM tableName
SELECT columnName FROM tableName WHERE columnName LIKE '%___###%' OR columnName LIKE '%___####%'
-- Will take a substring of this result as well
Example Data:
randomwebsite.com/3982356923abcd1ab?random_code=12480712_ABC_DEF_ANOTHER_CODE-xyz123&hello_world=us&etc_etc
In this case, the desired string is "xyz123" and the location of said pattern is variable based on each entry.
EDIT
SELECT column, LOCATE(column REGEXP "([a-zA-Z]{3}[0-9]{3,4}$)", column), SUBSTR(column, LOCATE(column REGEXP "([a-zA-Z]{3}[0-9]{3,4}$)", column), LENGTH(column) - LOCATE(column REGEXP "^.*[a-zA-Z]{3}[0-9]{3,4}", REVERSE(column))) AS extractData From mainTable
This expression is still not grabbing the right data, but I feel like it may get me closer.
I suggest using
REGEXP_SUBSTR(column, '(?<=[&?]random_code=[^&#]{0,256}-)[a-zA-Z]{3}[0-9]{3,4}(?![^&#])')
Details:
(?<=[&?]random_code=[^&#]{0,256}-) - immediately on the left, there must be & or &, random_code=, and then zero to 256 chars other than & and # followed with a - char
[a-zA-Z]{3} - three ASCII letters
[0-9]{3,4} - three to four ASCII digits
(?![^&#]) - that are followed either with &, # or end of string.
See the online demo:
WITH cte AS ( SELECT 'randomwebsite.com/3982356923abcd1ab?random_code=12480712_ABC_DEF_ANOTHER_CODE-xyz123&hello_world=us&etc_etc' val
UNION ALL
SELECT 'randomwebsite.com/3982356923abcd1ab?random_code=12480712_ABC_DEF_ANOTHER_CODE-xyz4567&hello_world=us&etc_etc'
UNION ALL
SELECT 'randomwebsite.com/3982356923abcd1ab?random_code=12480712_ABC_DEF_ANOTHER_CODE-xyz89&hello_world=us&etc_etc'
UNION ALL
SELECT 'randomwebsite.com/3982356923abcd1ab?random_code=12480712_ABC_DEF_ANOTHER_CODE-xyz00000&hello_world=us&etc_etc'
UNION ALL
SELECT 'randomwebsite.com/3982356923abcd1ab?random_code=12480712_ABC_DEF_ANOTHER_CODE-aaaaa11111&hello_world=us&etc_etc')
SELECT REGEXP_SUBSTR(val,'(?<=[&?]random_code=[^&#]{0,256}-)[a-zA-Z]{3}[0-9]{3,4}(?![^&#])') output
FROM cte
Output:
I'd make use of capture groups:
(?<=[=\-\\])([a-zA-Z]{3}[\d]{3,4})(?=[&])
I assume with [^=\-] you wanted to capture string with "-","\" or "=" in front but not include those chars in the result. To do that use "positive lookbehind" (?<=.
I also added a lookahead (?= for "&".
If you'd like to fidget more with regex I recommend RegExr

MySQL - need to find records without a period in them

I've been to the regexp page on the MySQL website and am having trouble getting the query right. I have a list of links and I want to find invalid links that do not contain a period. Here's my code that doesn't work:
select * from `links` where (url REGEXP '[^\\.]')
It's returning all rows in the entire database. I just want it to show me the rows where 'url' doesn't contain a period. Thanks for your help!
SELECT c1 FROM t1 WHERE c1 NOT LIKE '%.%'
Your regexp matches anything that contains a character that isn't a period. So if it contains foo.bar, the regexp matches the f and succeeds. You can do:
WHERE url REGEXP '^[^.]*$'
The anchors and repetition operator make this check that every character is not a period. Or you can do:
WHERE LOCATE(url, '.') = 0
BTW, you don't need to escape . when it's inside [] in a regexp.
Using regexp seems like an overkill here. A simple like operator would do the trick:
SELECT * FROM `links` WHERE url NOT LIKE '%.%
EDIT:
Having said that, if you really want to negate regexp, just use not regexp:
SELECT * FROM `links` WHERE url NOT REGEXP '[\\.]';

SQL Query to Search for String within a String (but the string may be separated)

I can't figure out the SQL query that would be able to select a row based on a column containing a string but the string could be separated.
For example, the string I am searching for:
1345
Would match:
0123456
That includes 3 things:
1) Any string before
2) Any string after
3) Any string randomly in the middle
I have tried using the following queries
SELECT * FROM Products WHERE FileName LIKE %1345%
SELECT * FROM Products WHERE CONTAINS(FileName, '1345')
But these will not select if the string is randomly in the middle. What should I be doing instead?
You'd need to pre-prepare for regexp match, so you produce a query like this
SELECT * from name1
WHERE name1.name REGEXP ".*a.*p.*a.*"
This is a working solution tested in MySQL Workbench:
SELECT * FROM Products WHERE FileName LIKE '%1%2%3%';
It matches entries like
2004267695, 2005285881, 20060004841, 20060136398, 20080189084, and 20090189887.
Folio 8 1/2 x 13 in
1992-2003

Query MySQL field for LIKE string

I have a field called 'areasCovered' in a MySQL database, which contains a string list of postcodes.
There are 2 rows that have similar data e.g:
Row 1: 'B*,PO*,WA*'
Row 2: 'BB*, SO*, DE*'
Note - The strings are not in any particular order and could change depending on the user
Now, if I was to use a query like:
SELECT * FROM technicians WHERE areasCovered LIKE '%B*%'
I'd like it to return JUST Row 1. However, it's returning Row 2 aswell, because of the BB* in the string.
How could I prevent it from doing this?
The key to using like in this case is to include delimiters, so you can look for delimited values:
SELECT *
FROM technicians
WHERE concat(', ', areasCovered, ', ') LIKE '%, B*, %'
In MySQL, you can also use find_in_set(), but the space can cause you problems so you need to get rid of it:
SELECT *
FROM technicians
WHERE find_in_set('B', replace(areasCovered, ', ', ',') > 0
Finally, though, you should not be storing these types of lists as strings. You should be storing them in a separate table, a junction table, with one row per technician and per area covered. That makes these types of queries easier to express and they have better performance.
You are searching wild cards at the start as well as end.
You need only at end.
SELECT * FROM technicians WHERE areasCovered LIKE 'B*%'
Reference:
Normally I hate REGEXP. But ho hum:
SELECT * FROM technicians
WHERE concat(",",replace(areasCovered,", ",",")) regexp ',B{1}\\*';
To explain a bit:
Get rid of the pesky space:
select replace("B*,PO*,WA*",", ",",");
Bolt a comma on the front
select concat(",",replace("B*,PO*,WA*",", ",","));
Use a REGEX to match "comma B once followed by an asterix":
select concat(",",replace("B*,PO*,WA*",", ",",")) regexp ',B{1}\\*';
I could not check it on my machine, but it's should work:
SELECT * FROM technicians WHERE areasCovered <> replace(areaCovered,',B*','whatever')
In case the 'B*' does not exist, the areasCovered will be equal to replace(areaCovered,',B*','whatever'), and it will reject that row.
In case the 'B*' exists, the areCovered will NOT be eqaul to replace(areaCovered,',B*','whatever'), and it will accept that row.
You can Do it the way Programming Student suggested
SELECT * FROM technicians WHERE areasCovered LIKE 'B*%'
Or you can also use limit on query
SELECT * FROM technicians WHERE areasCovered LIKE '%B*%' LIMIT 1
%B*% contains % on each side which makes it to return all the rows where value contains B* at any position of the text however your requirement is to find all the rows which contains values starting with B* so following query should do the work.
SELECT * FROM technicians WHERE areasCovered LIKE 'B*%'

Mysql like to match pattern at end of string

I have the following strings in the following pattern in a table in my db:
this_is_my_string_tester1
this_is_my_string_mystring2
this_is_my_string_greatstring
I am trying to match all strings that start with a specific pattern split by underscores i.e.this_is_my_string_ and then a wildcard final section
Unfortunately there is an added complication where some strings like the following:
this_is_my_string_tester1_yet_more_text
this_is_my_string_mystring2_more_text
this_is_my_string_greatstring_more
Therefore taking the following as examples:
this_is_my_string_tester1
this_is_my_string_mystring2
this_is_my_string_greatstring
this_is_my_string_tester1_yet_more_text
this_is_my_string_mystring2_more_text
this_is_my_string_greatstring_more
I am trying to have returned:
this_is_my_string_tester1
this_is_my_string_mystring2
this_is_my_string_greatstring
I have no idea how to do this with a like statement. Is this possible if so how?
EDIT
There is one final complication:
this_is_my_string
needs to be supplied as a list i.e in
(this_is_my_string, this_is_my_amazing_string, this_is_another_amazing_string)
SELECT * FROM atable WHERE afield REGEXP 'this_is_my_string_[a-z]+'
It might be faster if you have an index on afield and do
SELECT * FROM atable WHERE afield REGEXP 'this_is_my_string_[a-z]+'
AND afield LIKE 'this_is_my_string_%'
After edit of question:
Either
SELECT * FROM atable
WHERE afield REGEXP '(this_is_my_string|this_is_my_amazing_string)_[a-z]+'
or maybe you want something like having a table with the prefixes:
SELECT *
FROM atable AS t,
prefixes AS p
WHERE afield REGEXP CONCAT(p.prefix, '_[a-z]+')
As by the reference documentation this should not be possible, as a pattern (string literal) is required. Give it a try nevertheless.
There the answer of #KayNelson with LIKE (?) and INSTR might do instead of REGEXP.
try this
SELECT * FROM db.table WHERE strings LIKE 'this_is_my_string_%' AND instr(Replace(strings,"this_is_my_string_",""),"_") = 0;
It checks if more _ occurs after replacing the standard "this_is_my_string_"