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.
Related
I want to CONCAT value in ID column in string variable and use the variable with IN in SQL as under:
SET #ActID = CONCAT(CAST(5 AS CHAR),',',CAST(15 AS CHAR));
SELECT * FROM `accounts` WHERE `ID` IN (#ActID);
It returns record having ID = 5 and ignore record having ID = 15.
#ActID is a comma separated list string literal and not a list of values.
So the list inside the parentheses of the IN operator contains only 1 value: '5,15'
when you compare 5 to '5,15' the result is TRUE
when you compare 15 to '5,15' the result is FALSE
because '5,15' is converted to the integer value 5 according to the rules described here.
What you want is the function FIND_IN_SET():
SET #ActID = CONCAT(CAST(5 AS CHAR),',',CAST(15 AS CHAR));
SELECT * FROM `accounts` WHERE FIND_IN_SET(`ID`,#ActID) > 0;
Change to ...= 0 for the equivalent of NOT IN.
See a simplified demo.
Note: SET #ActID = CONCAT(5,',',15); works fine.
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
I would like to round up a value to the next nearest power of 2 in a mysql query, so
select RoundUpToNearestPowerOfTwo(700) -- Should give 1024
I need this solution as part of a much larger query to generate and read some bitmask. Using custom stored functions is not an option, since I cannot use those in our production environment, so I'm looking for a smart way to do this inline in the query.
[Edit]
One possible way I can think of, is creating some enumerator, use a power in that, and choose the smallest value larger than my value:
select
min(BOUND)
from
(select 700 as VALUE) v
inner join
(select
POW(2, #pow := #pow + 1) as BOUND
from
(select #pow := 0) x,
MY_RANDOM_TABLE t
) x on x.BOUND > v.VALUE
But as you can tell, it's pretty verbose, so a leaner solution would be welcome.
Try this.
FLOOR(POW(2,CEIL(LOG2(1025))))
The CEIL and FLOOR cope with the boundary conditions correctly.
Try this:
select power(2, 1 + floor(log2(XXX)))
MySQL conveniently has the log2() function, which does most of the work.
EDIT:
I think this may be what you want:
select (case when floor(log2(XXX)) <> log2(XXX)
then power(2, 1 + floor(log2(XXX)))
else power(2, floor(log2(XXX)))
end)
Or something like:
select power(2, 1 + floor(log2(XXX*0.999999)))
There is a boundary condition on actual powers of 2.
If you are using SQL Server then you can try this...just change value in variable #value for any value to get the next nearest power of 2
declare #count int = 1
declare #value int = 700
while (#value <> 1)
BEGIN
set #value = #value / 2
set #count = #count + 1
END
select power(2, #count)
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 ;
I need to find all rows in a MySQL database that fall between "YYYY-10-30" and "YYYY-12-11" I don't care about which year the the date is in just that falls between the two dates.
SELECT *
FROM yourTable
WHERE (MONTH(yourDate) = 10 AND DAYOFMONTH(yourDate) >= 30)
OR (MONTH(yourDate) = 11)
OR (MONTH(yourDate) = 12 AND DAYOFMONTH(yourDate) <= 11)
select *
from table
where
concat(year(now()),right(date_field,6))
between
concat(year(now()),'-10-30')
and
concat(year(now()),'-12-11')
Could you try this?:
CREATE DEFINER=`root`#`localhost` PROCEDURE `GetByMonthAndDayRange`
(
IN monthFrom INT
, IN dayFrom INT
, IN monthTo INT
, IN dayTo INT
)
BEGIN
-- For good coding practice, name your columns instead of using *
SELECT *
FROM tablename
WHERE
(MONTH(datecolumnname) = monthFrom AND DAYOFMONTH(datecolumnname) >= dayFrom)
OR (MONTH(datecolumnname) > monthFrom AND MONTH(datecolumnname) < monthTo)
OR (MONTH(datecolumnname) = monthTo AND DAYOFMONTH(datecolumnname) <= dayTo);
END
If you use a stored procedure (and if the code works to your taste) you'll be able to code faster, just providing the parameters (it's dynamic this way)