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 |
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
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
I have a table, let's call it A, with a FULLTEXT index on its name field.
This table, containing around 1200 rows, contains a single row whose name field has a value of "TELEVISORI"
This query:
SELECT A.name, MATCH(name) AGAINST ('Televisori') AS `match`
FROM A
Results in (not the exact value, but I remember it being around 8):
+------------+-----------+
| name | match |
+------------+-----------+
| TELEVISORI | 8.3947893 |
+------------+-----------+
Whereas this one:
SELECT A.name, MATCH(name) AGAINST ('Televisore') AS `match`
FROM A
yields no results.
Things I've checked:
The word is not a stop word
Its length is over 4 characters (rather, 3 since I'm using InnoDB?)
The word appears in less than 50% of records - It's the only one in hundreds.
I tried changing the casing of the words in every possible combination just to be completely sure, but that shouldn't be it since I'm using a case insensitive collation. Also, it matches without a problem when I use "Televisori"
Is there anything I'm missing?
I have a table that is populated with certain values e.g.
| CODE | NAME | NB: THIS IS A VERY BASIC EXAMPLE
| zygnc | oscar alpha |
| ab-cd | delta tiger |
| fsdys | delta bravo |
Using MySQL Full-Text Boolean search i would like to search this table for all names containing 'delta' but exclude the first result basic on its unique code 'ab-cd'. This code contains a minus sign and this is a requirement and removing this would not be possible.
So the following query 'should' in my mind accommodate for this:
SELECT code, name
FROM items
WHERE MATCH (code, name)
AGAINST ('delta -"ab-cd"' IN BOOLEAN MODE)
However, running this query does not product the desired result in that the result does still contain the row with the code that is meant to be excluded, 'ab-cd'.
The Coalition of these two tables are set to utf8_bin.
The ft_min_word_len value is set to 4.
Could someone possibly suggest a reason for this behavior, I assume that it treats the string possibly as two separate values, e.g. "-ab", "-cd" and as the ft_min_word_len value is 4, neither of these two strings can produce any result?
I would think that the use of the encapsulation "", would mean that the second minus sign would be treated as literal but it seems that this is not the case. Perhaps it has something to do with the table coalition that i am not aware of?
In any case, any suggestions/advice/input/feedback/direction would be greatly appreciated, thank you!!
You need to change the value of variable ft_min_word_len in my.cnf file.
By default ft_min_word_len value is 3. Once change the variable, you need to restart the server.
Here "ab-cd" treated as two words as "ab" and "cd". So minimum word length is not matched with the words.
I have a table that has a comma separated list of ids in one of the fields (not my doing). I want to know if I can use LIKE to match a number in this string? The problem is I don't want to get similar numbers. Is there a way to match a number with no numeric charcters on either side?
SELECT * FROM table WHERE activitiesids LIKE 6
| activitiesids |
---+---------------+---
| 3,16,8,6 |
---+---------------+---
| 6 |
---+---------------+---
| 7,560 |
---+---------------+---
Haven't tested but you can try something like this:
SELECT * FROM table WHERE activitiesids REGEXP '[[:<:]][0-9]+[[:>:]]';
Something like that:
WHERE ids LIKE '%,16,%' OR ids LIKE '%,16' OR ids LIKE '16,%';
Postgresql even has pattern matching - I don't know for mysql:
WHERE ids ~ '^(.*,)?16(,.*)?$';