using regualr expression in mysql to select specific rows - mysql

I'm trying to select a small set of records that match a patten I have a series of numbers in each row such as
1
2
3
some of them have sub numbers
3.1
3.2
4
5
I can select only the whole numbers using
REGEXP '^[0-9]+$'
I can select all rows that have a . in them like 3.1 3.2 etc using
REGEXP '[.]{1}'
but I can't seem to select for example only sub numbers that start with 3 I've tried
REGEXP '[^3.]{1,}'
but that returns all records
Ideally I want to return only records that are in the format of 3.1 I would like to define the start number and the dot so 3. then the second part match against the records
I hope this makes sense

I used '3\.[0-9]{1,}' - it matched.
Yours probably fails because of unescaped dot - ., which matches every character.
Escape characters with \

Format 3.d where d is digit:
3\\.[0-9]

Related

MYSQL - Find rows, where part of search string matches part of value in column

I wasn't able to find this anywhere, here's my problem:
I have a string like '1 2 3 4 5' and then I have a mysql table that has a column, let's call it numbers, that look like this:
numbers
1 2 6 8 9 14
3
1 5 3 6 9
7 8 9 23 44
10
I am trying to find the easiest way (hopefully in a single query) to find the rows, where any of the numbers in my search string (1 or 2 or 3 or 4 or 5) is contained in the numbers column. In the give example I am looking for rows with 1,2 and 3 (since they share numbers with my search string).
I am trying to do this with a single query and no loops.
Thanks!
The best solution would be to get rid of the column containing a list of values, and use a schema where each value is in its own row. Then you can use WHERE number IN (1, 2, 3, 4, 5) and join this with the table containing the rest of the data.
But if you can't change the schema, you can use a regular expression.
SELECT *
FROM yourTable
WHERE numbers REGEXP '[[:<:]](1|2|3|4|5)[[:<:]]'
[[:<:]] and [[:<:]] match the beginning and end of words.
Note that this type of search will be very slow if the table is large, because it's not feasible to index it.
Here is a start point (split string function) : http://blog.fedecarg.com/2009/02/22/mysql-split-string-function/ := SplitString(string,delimiter,position)
Create a function so it converts a string to an array := stringSplitted(string,delimiter)
Create a function so it compares two arrays :=arrayIntersect(array1, array2)
SELECT numbers
FROM table
WHERE arrayIntersect(#argument, numbers)
Two function definitions with loops and one single query without any loop
SELECT * FROM MyTable WHERE (numbers LIKE '%1%' OR numbers LIKE '%2%')
or you can also use REGEX something like this
SELECT * FROM events WHERE id REGEXP '5587$'

Transforming a column to have 10 Digits

I have a csv file that contains phone numbers, some of them have 9 digits and some of them have 10. Is there a command that would allow the transformation of the column such that numbers that have only 9 digits will have a 0 appended in front of the numbers.
For example,
if the column has values "443332332" and "0441223332", I would like to have the value of the one with 9 digits changed to "0443332332"?
Sorry, I should have elaborated.
I was wondering if there was a command to do it in SQLlite easily? I prefer not to use excel to transform the column as if I can get it to working with sqllite it would be so much easier and faster.
A more generic solution would be:
select substr('0000000000'||'1234567', -10, 10) from table_name;
The above query would always return 10 digits and add leading zeroes to the missed out number of digits.
For example, the above query would return : 0001234567
For Update, use
UPDATE TABLE_NAME SET PHONE_NO = substr('0000000000'|| PHONE_NO, -10, 10);
If you're sure that just prepending a zero on strings with length 9 will work for your application, something simple will work:
SELECT CASE WHEN LENGTH(phone_number) = 9 THEN '0'||phone_number
ELSE phone_number
END AS phone_number
FROM your_table
;
You could also update the table, depending on your needs:
UPDATE your_table
SET phone_number = '0'||phone_number
WHERE LENGTH(phone_number) = 9
;
Open the .csv using Excel,
Add a filter to the column,
Sort from A-Z to get all the columns with 9 digits,
Then follow the steps here
http://office.microsoft.com/en-au/excel-help/keep-leading-zeros-in-number-codes-HA010342581.aspx

substring dynamic number of characters

I'm working with 2 sets of data that were merged together, but they're inconsistent in their format. Some are 10 characters, all numbers. Others may have a separator : at position 4. I need to substring the first 4 characters. But if the 4th character is a : substring only the first 3 characters.
Does mysql have an IF functionality to determine the number of characters to substring based on the character in position 4?
select substring(id, 1 , 3/4) from table1
You can treat the field like it's colon separated and do this to select only the first part:
SELECT SUBSTRING_INDEX(id, ':', 1)
See also: SUBSTRING_INDEX()

mysql replace string + next one char

Is it possible to REPLACE a string + next character in MySQL? Something like LIKE underscore.
For example, if text column is this:
12 13 14 14_B 15 14_A, REPLACE all 14_* with an empty character, and replaced text should be:
12 13 14 15
You'll be looking to do this using a regular expression UDF in MySQL. Key ingredients are
regular expression UDF - check here
The regular expression itself
If you will ONLY ever see 2 to 4 of these that you need replaced, a poor man's working approach (SQL Fiddle):
SELECT *,IF(LOCATE('14_',B)+3<=Length(B),
INSERT(B,LOCATE('14_',B),4,''),B) C
FROM
(
SELECT *,IF(LOCATE('14_',A)+3<=Length(A),
INSERT(A,LOCATE('14_',A),4,''),A) B
FROM (
SELECT *,IF(LOCATE('14_',x)+3<=Length(X),
INSERT(X,LOCATE('14_',x),4,''),X) A
FROM X
) Q1
) Q2
I've only catered for 3 replacements but you can easily expand the pattern. Include only the columns from the base table needed in the outermost query.

MySQL Regular Expression Match

I am trying to update my product database and find duplicates after some product numbers where changed.
In the past the changed item numbers just had an extra dash and number or letter on the end and I used this where clause:
where a.ProdNum REGEXP CONCAT('^', b.ProdNum, '(\-|\s)[a-zA-Z0-9]+')
Now the REGEXP is over my head.
Old Product number: BRB-0325
New Product number: 0325-15 (the number after the dash can be any 1 or 2 digit number)
So basically I need a where clause that will drop the "BRB-" from the Old Number and drop any 1 or 2 digit number after the new item number.
I can do the dropping of the "BRB-", but not sure how to handle dealing with the 1-2 digit number, and I really don't know how to do both at the same time.
where b.ProdNum = CONCAT('BRB-', c.ProdNum)
Here is what I tried with the 2 digits and that didn't work.
where c.ProdNum REGEXP CONCAT('^', b.ProdNum, '(\-)[0-9]{1,2}+')
Thanks for your help.
Assuming c.ProdNum is the new number and b.ProdNum is the old:
WHERE CONCAT('BRB-', c.ProdNum) REGEXP CONCAT('^', b.ProdNum, '-[0-9]{1,2}$')
This adds "BRB-" to the new number and compares it to the old. So you will be essentially comparing "BRB-0325-15" with "BRB-0325-nn".
Why are you using REGEXP? Use a straightforward comparison:
where a.ProdNum like concat(substring(b.ProdNum, 4), '-??')
This will match 0325-ab, but surely you don't have such new product numbers.
This should work for you:
SELECT
old.*
FROM
products old,
products new
WHERE new.ProdNum REGEXP CONCAT('^', SUBSTRING(old.ProdNum, 5), '-[0-9]{1,2}$')
AND old.ProdNum LIKE 'BRB-%'
This should use an index on ProdNum if one is available.