In my MySQL database I have a row column called test_column with the following rows:
dtq test dis
ged something fbd
edf something tds
zhs nothing edk
dda anything zhg
hvf nothing ert
asf nothing vbg
I'm looking for the string between the first three and the last three characters. I can get these values with REGEX like this:
^\w{3}\s(\w+)\s\w{3}$
I want to SELECT DISTINCT these values.
Expected output is the following:
test
something
nothing
anything
How can I do that with a MySQL command?
If you are running MySQL 8.0, you can use regexp_replace() as follows:
select distinct regexp_replace(col, '(^\\w{3}\\s)|(\\s\\w{3}$)', '') new_col from mytable
This works by replacing the first and last words (and the following/preceding spaces) with the empty string. The first and last words must be 3 characters long.
Demo on DB Fiddle:
| new_col |
| :-------- |
| test |
| something |
| nothing |
| anything |
You can make the regex a little more generic so it accepts also starting and ending words that have a length other than 3 characters and sequences of more than one space:
regexp_replace(col, '(^\\w+\\s+)|(\\s+\\w{+$)', '')
Don't need a regexp if this suffices
SUBSTRING_INDEX(col, ' ', 2)
However, this assumes your "3 characters" or \w{3} (which is really 3 alphanumeric characters) is not really the test, but instead the space is critical.
You don't need regex if that is all you want (remove first 4 and last 4 characters):
SELECT DISTINCT SUBSTRING(test_column,5,LENGTH(test_column)-8)
FROM mytable
Demo on dbfiddle.uk
or everything after the first space, up until the second space:
SELECT DISTINCT SUBSTRING_INDEX(SUBSTRING_INDEX(test_column,' ',2),' ',-1)
FROM mytable
Demo on dbfiddle.uk
Related
I have a data base column (comment) with almost any combination of alpha characters, numbers or alphanumerics can appear. In one example it looks like this this 55,44,1265,13,12 in another it might be 12,55,1265,44,13 there also might be A45, or 45A or ABCDE52JQST or 12 13 15 or anything really.
I need a MySQL query to extract any row based on a search entered by the user. For example the user might want to identify all rows with 12 in it. Not 1265 not 12A just 12, the only acceptable values other than 12 would be ,12 or 12, (comma12 or 12comma) or spaces before or after the number ( 12 or 12 ). But not 1265.
My current where clause looks like below and while it sometimes works, it sometimes doesn't and even if it did work every time, it's ugly. How else could I write the where clause to do what I need, could I use perl expressions in some way? Please give an example.
WHERE netID = $netID
AND
( comment LIKE '%$findit'
OR comment LIKE '$findit%'
OR comment = '$findit'
OR comment = ',$findit'
OR comment = '$findit,'
OR comment = ',$findit,'
OR comment LIKE '% $findit '
OR comment LIKE ' $findit %'
OR comment LIKE '%$findit,'
OR comment LIKE ',$findit%'
OR comment LIKE '%,$findit'
OR comment LIKE '$findit,%'
OR comment LIKE '%,$findit '
OR comment LIKE ' $findit,%'
OR comment LIKE '% $findit'
OR comment LIKE '$findit %'
OR comment LIKE '%$findit '
OR comment LIKE ' $findit%'
OR comment LIKE '%,$findit,%'
)
You seem to be describing set data with either commas or spaces as delimiters. Instead of going into the typical lecture on storage of serialised data, I will just assume there is nothing you can do about it.
Obviously, passing strings directly into your SQL like this poses a SQLi risk and you should be using parameterised queries or at least some robust sanitisation and validation of the user input.
So, treat the set as a set by turning the space separated lists into comma separated lists -
WHERE FIND_IN_SET('$findit', REPLACE(`comment`, ' ', ',')) > 0
FIND_IN_SET
REPLACE
PREPARED STATEMENTS
UPDATE
This db<>fiddle works for the examples you have provided. Please provide a specific example of value(s) for which this does not work. Using REGEXP as suggested by Kendle/Bill Karwin may be the better route to go down.
In MYSQL we can use regular expressions. Here we use the expression (?<![0-9])12(?![0-9]) which means that the string must contain 12 and, if the are characters before or after it, the one touching it must not be a number.
We use a negative lookback and a negative look forward.
create table base(
val varchar(100));
insert into base values
('55,44,1265,13,12'),
('12,55,1265,44,13'),
( 'A45, or 45A or '),
(' ABCDE52JQST 1265'),
('12 13 15 or a'),
('123,212, '),
('haza12'),
(1265),
(1212),
(12),
(2012);
select val from base
where val regexp
'(?<![0-9])12(?![0-9])'
| val |
| :--------------- |
| 55,44,1265,13,12 |
| 12,55,1265,44,13 |
| 12 13 15 or a |
| haza12 |
| 12 |
db<>fiddle here
So I have a slug column in my table and due to some bad coding, some of my slugs are messed up and need to be fixed.
I need to find all slugs that have a hyphen on both sides of exactly 5 digits, somewhere in the middle of the string.
So here's three samples of slugs:
321-sw-2nd-ave-portland-or-97204-2-3-4-5
321-sw-2nd-ave-portland-or-97204-2-3
430-e-25th-st-tacoma-wa-98421
My expression would match the first and second but not the third one.
I would like to then get rid of those extra things after the zip code.
Here's what I have tried so far, but my Regex skills are lacking big time.
^(.)*d{5}-(.)*$
You are attempting to match on the entire string. I would simply do a partial match on the part that you are interested in. Another problem with your regex is that you use d to represent a digit: MySQL wants \\d; also, this notation is only supported from 8.0 (in earlier versions, you need [0-9]).
Consider:
slug RLIKE '[0-9]{5}-'
Demo on DB Fiddle:
with t as (
select '321-sw-2nd-ave-portland-or-97204-2-3-4-5' slug
union all select '321-sw-2nd-ave-portland-or-97204-2-3'
union all select '430-e-25th-st-tacoma-wa-98421'
)
select slug from t where slug RLIKE '[0-9]{5}-'
| slug |
| :--------------------------------------- |
| 321-sw-2nd-ave-portland-or-97204-2-3-4-5 |
| 321-sw-2nd-ave-portland-or-97204-2-3 |
Is there a built in way in mysql to query columns that contains specific word(s) and the word(s) also start with the input.
For instance, input is "EF"
#1 ABCD EFGH <- Want this one
#2 BCDE FGHA
#3 CDEF GHAB
#4 EFGH ABCD <- And this one
If I query %EF%, it'll give me the #1, #3 and #4, if I query EF%, it's only going to give #4.
So essentially, I want to know if mysql can firstly do a preg_split like in PHP, then query EF%, or something along the line of that.
Use a regular expression. In MySQL, the regexp pattern [[:<:]] matches the beginning of a word, so you can do:
WHERE column REGEXP '[[:<:]]EF'
Documentation
Answering my own question here. Just came up with a solution, not pretty but it works.
I just changed my parameter into this
((Column LIKE '%...%' AND Column LIKE '% ...%') Or (Column LIKE '...%')) AND ...
Going to leave this here for a day and see if anyone has a better solution.
If your column has two words, then you can use SUBSTR() and LOCATE().
+--------------------------------+
| MyColumn |
+--------------------------------+
| Apple Effect |
| Effortless Orange |
+--------------------------------+
.
SELECT *
FROM (
SELECT
*,
SUBSTR(#values,1,LOCATE(' ',MyColumn)-1) AS FirstWord
SUBSTR(#values,LOCATE(' ',#values)+1) AS SecondWord
FROM MyTable
) AS X
WHERE FirstWord LIKE 'EF%'
OR SecondWord LIKE 'EF%'
If your column has more than two words, then things are a little more complex, but you can use SUBSTRING_INDEX() to find the Nth instance.
+--------------------------------+
| MyColumn |
+--------------------------------+
| The Perfect Apple Effect |
| The Special Effortless Orange |
+--------------------------------+
.
SUBSTRING_INDEX(SUBSTRING_INDEX(#values,' ',4),' ',-1) = Gets the fourth word.
More examples and information can be found here.
I have a query I need to run on almost 2000 strings where it would be very helpful to be able to do a list like you can with the "IN" operator but using the LIKE comparison operation.
For example I want to check to see if pet_name is like any of these (but not exact): barfy, max, whiskers, champ, big-D, Big D, Sally
Using like it wouldn't be case sensitive and it can also have an underscore instead of a dash. Or a space. It will be a huge pain in the ass to write a large series of OR operators. I am running this on MySQL 5.1.
In my particular case I am looking for file names where the differences are usually a dash or an underscore where the opposite would be.
For this task I would suggest making use of RegExp capabilities in MySQL like this:
select * from EMP where name RLIKE 'jo|ith|der';
This is case insensitive match and will save from multiple like / OR conditions.
You could do something like this -
SELECT FIND_IN_SET(
'bigD',
REPLACE(REPLACE('barfy,max,whiskers,champ,big-D,Big D,Sally', '-', ''), ' ', '')
) has_petname;
+-------------+
| has_petname |
+-------------+
| 5 |
+-------------+
It will give a non-zero value (>0) if there is a pet_name we are looking for.
But I'd suggest you to create a table petnames and use SOUNDS LIKE function to compare names, in this case 'bigD' will be equal to 'big-D', e.g.:
SELECT 'bigD' SOUNDS LIKE 'big-D';
+---------------------------+
| 'bigD'SOUNDS LIKE 'big-D' |
+---------------------------+
| 1 |
+---------------------------+
Example:
CREATE TABLE petnames(name VARCHAR(40));
INSERT INTO petnames VALUES
('barfy'),('max'),('whiskers'),('champ'),('big-D'),('Big D'),('Sally');
SELECT name FROM petnames WHERE 'bigD' SOUNDS LIKE name;
+-------+
| name |
+-------+
| big-D |
| Big D |
+-------+
As first step put all static values in any temporary table, this would be lookup dictionary.
SELECT * FROM Table t
WHERE EXISTS (
SELECT *
FROM LookupTable l
WHERE t.PetName LIKE '%' + l.Value + '%'
)
Configure the column containing those 2000 values for full-text searching. Then you can use MySQL's full-text search feature. Refer to their docs
You could use REGEXP instead. It worked like a charm for me
pet_name regexp 'barfy|max|whiskers|champ|you name it'
I am using MySQL.
I have a car table in my database, and there is a name column in that table.
Suppose the name column of the table contain values:
+----------+
| name |
+----------+
| AAA BB |
----------
| CC D BB |
----------
| OO kk BB |
----------
| PP B CC |
----------
I would like to search the table where name column value contains word "BB" (not substring), What is the SQL command to achieve this ?
I know LIKE , but it is used to match a contained substring, not for a word match.
P.S.
My table contains large data. So, I probably need a more efficient way than using LIKE
The values in name column are random strings.
Please do not ask me to use IN (...) , because the values in that column is unpredictable.
Try this WHERE clause:
WHERE name LIKE '% BB %'
OR name LIKE 'BB %'
OR name LIKE '% BB'
OR name = 'BB'
Note that this will not perform well if your table is large. You may also want to consider a full-text search if you need better performance.
You can use the REGEXP operator in MySQL:
SELECT *
FROM car
WHERE name REGEXP '[[:<:]]BB[[:>:]]'
It will match BB if it occurs as a single word. From the MySQL manual:
[[:<:]], [[:>:]]
These markers stand for word boundaries. They match the beginning and end of words, respectively. A word is a sequence of word characters that is not preceded by or followed by word characters. A word character is an alphanumeric character in the alnum class or an underscore (_).
mysql> SELECT 'a word a' REGEXP '[[:<:]]word[[:>:]]'; -> 1
mysql> SELECT 'a xword a' REGEXP '[[:<:]]word[[:>:]]'; -> 0