Find a string in a MySQL field with concurrences - mysql

Is there any function in MySQL where I especifies the concurrences numbers for the search?
Example:
lcString = "My name-is-Harry-Potter"
In Visual FoxPro you can use this:
?AT('a',lcString,1) && where 1 means "get me the first concurrence"
OutPut = 5
Or
?AT('-',lcString,3) && where 3 means "get me the third concurrence"
OutPut = 17
I was looking for a similar function in mysql but I can't find it.
Thank you all...!!!

You can use SUBSTRING_INDEX and LENGTH MySQL functions to achieve that. This is what MySQL's documentation says about SUBSTRING_INDEX:
Returns the substring from string str before count occurrences of the
delimiter
So, you can wrap that inside LENGTH to get the occurrence, e.g.:
SELECT LENGTH(SUBSTRING_INDEX('My name-is-Harry-Potter', 'a', 1)) + 1
SELECT LENGTH(SUBSTRING_INDEX('My name-is-Harry-Potter', '-', 3)) + 1

Related

query for serial number

Just want to get an idea & advise.. how to get the exact result for my situation when query..see below table..
I try to use this query and its look fine..but the problem is when I give the input ABC1001Z (different only last character Z).. the query still return Honda as result.. it's supposed not return any result/no result found.. any solution for my case?
SELECT Name
FROM CarNo
WHERE ('ABC1001Z' BETWEEN Start AND End)
AND (len('ABC1001Z') = len (Start));
Your kind support is much appreciated..
Update you code to
SELECT Name FROM CarNo
WHERE (SUBSTRING('ABC1001Z',0,7) BETWEEN SUBSTRING(Start,0,7) AND SUBSTRING(End,0,7) )
AND (len('ABC1001Z') = len (Start));
Maybe that's what you are looking for:
SELECT Name FROM CarNo
WHERE (Start = 'ABC1001Z' OR End = 'ABC1001Z')
AND (len('ABC1001Z') = len(Start));
You seem to want the "number" in the middle to be treated as a number. This suggests something like this:
where left('ABC1001Z', 3) between left(start, 3) and left(end, 3) and
substr('ABC1001Z', 4, 4) + 0 between substr(start, 4, 4) + 0 and substr(end, 4, 4) + 0
I'm not sure how the last character relates to a between query of this form, so I'm not addressing that.

Compare string in database

I have these entries in database.
Numbers at the end are versions, i.e 10.0, 9.1, 9.0. I need to compare the entries and I used a query like,
select * from Fault_Profile where PROFILE_NAME < 'DEFAULT_9.1';
But the entries are comapred like string, and returns values with 10.0 (I know it is obivous).
But is there any way using sql queries to extract number out of the string and compare it like numbers.
NOTE : This is old design in my project can't change schema can't change values.
You can use SUBSTR() then retype to DOUBLE
SELECT *
FROM Fault_Profile
WHERE SUBSTRING(PROFILE_NAME, 9) < 9.1;
May not be an efficient one but you can try something like below, which will return only the part after _. i.e, 10.0, 9.1, 9.0
select
substring('Default_9.0',
locate('_','Default_9.0')+1,
(length('Default_9.0') - locate('_','Default_9.0')))
So, per your query it should be
select *
from Fault_Profile
where
substring(PROFILE_NAME,
locate('_',PROFILE_NAME)+1,
(length(PROFILE_NAME) - locate('_',PROFILE_NAME))) < 9.1
CREATE FUNCTION PROFILE_NAME_VERSION
(
-- Add the parameters for the function here
#PROFILE_NAME nvarchar(100)
)
RETURNS float
AS
BEGIN
-- Declare the return variable here
DECLARE #ResultVar float
SET #ResultVar=CAST(REPLACE(#PROFILE_NAME,'DEFAULT_','') as float)
RETURN #ResultVar
END
GO
select * from Fault_Profile where dbo.PROFILE_NAME_VERSION(PROFILE_NAME) < 9.1
Replace the size of the function parameter for match your size
you can use REPLACE too
SELECT *
FROM Fault_Profile
where REPLACE(PROFILE_NAME, 'Default_','')*1 < 9.1
SQL Fiddle:
SELECT *
FROM Fault_Profile
WHERE CAST(RIGHT(PROFILE_NAME, CHARACTER_LENGTH(PROFILE_NAME) - INSTR(PROFILE_NAME, '_')) AS DECIMAL(3,1)) < 9.1
ORDER BY CAST(RIGHT(PROFILE_NAME, CHARACTER_LENGTH(PROFILE_NAME) - INSTR(PROFILE_NAME, '_')) AS DECIMAL(3,1));
Or if this looks better to you (SQL Fiddle):
SELECT m.PROFILE_NAME, m.ALARM_CLASS FROM
(
SELECT *,
CAST(RIGHT(PROFILE_NAME, CHARACTER_LENGTH(PROFILE_NAME) - INSTR(PROFILE_NAME, '_')) AS DECIMAL(3,1)) AS version
FROM Fault_Profile f
) AS m
WHERE m.version < 9.1
ORDER BY m.version, m.ALARM_CLASS
The above query does assume that the characters after the _ will be the numeric version number. However, you can have as many characters as you need in front of the _. So for instance it will still work with; Beta_9.0 and Production_10.1.

Mysql: concatenation symbol inside Concat with conditional statement

Sql:
concat(Discount,'% ',if(Net_Deferred=0,' Spot Cash',Net_Deferred, ' months deferral'))
The issue:
if(...Net_Deferred, ' months deferral'..
The comma that concatenate the 2 strings throws an error because if statement only works on 2 commas (true or false)
The result should look like this:
If(Net_Deferred=0) : Spot Cash
else : 24 months deferral
value 24 comes from Net_Deferred field.
Question:
How to concatenate field inside concat with if else statement?
You can use concat again
IF(Net_Deferred = 0, " Spot Cash", CONCAT(Net_Deferred, " months deferral"))

Updating column values as per our format

There are two types of records in my Db such as MS-NW and CS in the same column of table DICIPLINE I want to wrap if its CS (ANY TWO STRING LIKE CS,TE OR THE LIKE) then wrap it to BS(CS) (OR BS(TE) ETC) or if its MS-NW (Or MS-CS, MS-TE and the like) then wrap it to MS(NW) from the column dicipline.
I updated for two strings successfully and following is the query for that kindly let me know how can i do it for values like MS-NW OR MS-CS and convert it to the format like MS(NW) from following query .
UPDATE DEG set DICIPLINE = concat("BS(",DICIPLINE,")") where CHAR_LENGTH(DICIPLINE) = 2
The below query helps you to update your data.
update deg set DISIPLINE = if(length(DISIPLINE)= 2,concat('BC(',DISIPLINE,')')
,concat('MS(',substr(DISIPLINE, 4,4),')'));
See Sqlfiddle demo.
For safety, create a temporary column of same type and perform an update like this:
UPDATE deg
SET dicipline_temp = CASE
WHEN CHAR_LENGTH(dicipline) = 2
THEN CONCAT('BS(', dicipline, ')')
WHEN CHAR_LENGTH(dicipline) = 5 AND SUBSTRING(dicipline, 3, 1) = '-'
THEN CONCAT(REPLACE(dicipline, '-', '('), ')')
END
WHERE CHAR_LENGTH(dicipline) = 2 OR (CHAR_LENGTH(dicipline) = 5 AND SUBSTRING(dicipline, 3, 1) = '-')
If results are acceptable, update the actual column.

How to find the first number in a text field using a MySQL query?

I like to return only the first number of a text stored in a column of a database table.
User have put in page ranges into a field like 'p.2-5' or 'page 2 to 5' or '2 - 5'.
I am interested in the '2' here.
I tried to
SELECT SUBSTR(the_field, LOCATE('2', the_field, 1)) AS 'the_number'
FROM the_table
and it works. But how to get ANY number?
I tried
SELECT SUBSTR(the_field, LOCATE(REGEXP '[0-9], the_field, 1)) AS 'the_number'
FROM the_table
but this time I get an error.
Any ideas?
Just use REGEXP_SUBSTR():
SELECT REGEXP_SUBSTR(`the_field`,'^[0-9]+') AS `the_number` FROM `the_table`;
Notes:
I'm using MySQL Server v8.0.
This pattern assumes that the_field is trimmed. Otherwise, use TRIM() first.
REGEXP is not a function in MySQL, but something of an operator. Returns 1 if field matches the regular expression, or 0 if it does not. You cannot use it to figure out a position in a string.
Usage:
mysql> SELECT 'Monty!' REGEXP '.*';
-> 1
As for answer to the question: I don't think there is a simple way to do that using MySQL only. You would be better off processing that field in the code, or extract values before inserting.
For the specific case in the question. Where the String is {number}{string}{number}
there is a simple solution to get the first number. In our case we had numbers like 1/2,3
4-10
1,2
and we were looking for the first number in each row.
It turned out that for this case one can use convert function to convert it into number. MySQL will return the first number
select convert(the_field ,SIGNED) as the_first_number from the_table
or more hard core will be
SELECT
the_field,
#num := CONVERT(the_field, SIGNED) AS cast_num,
SUBSTRING(the_field, 1, LOCATE(#num, the_field) + LENGTH(#num) - 1) AS num_part,
SUBSTRING(the_field, LOCATE(#num, the_field) + LENGTH(#num)) AS txt_part
FROM the_table;
This was original post at source by Eamon Daly
What does it do?
#num := CONVERT(the_field, SIGNED) AS cast_num # try to convert it into a number
SUBSTRING(the_field, 1, LOCATE(#num, the_field) + LENGTH(#num) - 1) # gets the number by using the length and the location of #num in field
SUBSTRING(the_field, LOCATE(#num, the_field) + LENGTH(#num)) # finds the rest of the string after the number.
Some thoughts for future use
Its worth keeping another column which will hold the first number after you parsed it before insert it to the database. Actually this is what we are doing these days.
Edit
Just saw that you have text like p.2-5 and etc.. which means the above cannot work as if the string does not start with a number convert return zero
There's no built-in way that I know of, but here's a Mysql function you can define, this will do it (I didn't code for minus-signs or non-integers, but those could of course be added).
Once created, you can use it like any other function:
SELECT firstNumber(the_field) from the_table;
Here's the code:
DELIMITER //
CREATE FUNCTION firstNumber(s TEXT)
RETURNS INTEGER
COMMENT 'Returns the first integer found in a string'
DETERMINISTIC
BEGIN
DECLARE token TEXT DEFAULT '';
DECLARE len INTEGER DEFAULT 0;
DECLARE ind INTEGER DEFAULT 0;
DECLARE thisChar CHAR(1) DEFAULT ' ';
SET len = CHAR_LENGTH(s);
SET ind = 1;
WHILE ind <= len DO
SET thisChar = SUBSTRING(s, ind, 1);
IF (ORD(thisChar) >= 48 AND ORD(thisChar) <= 57) THEN
SET token = CONCAT(token, thisChar);
ELSEIF token <> '' THEN
SET ind = len + 1;
END IF;
SET ind = ind + 1;
END WHILE;
IF token = '' THEN
RETURN 0;
END IF;
RETURN token;
END //
DELIMITER ;