Remove trailing zeros in decimal value with changing length - mysql

I have a procedure I am doing that displays odds but the client wants only significant digits to be shown. So, 1.50 would show as '1.5' and 1.00 would show as '1'.
How can I get MySQL to not display trailing zeros;
i.e. in the database:
Odds
1.500
23.030
2.000
4.450
would display as
1.5
23.03
2
4.45
Thanks for any help

Easiest way by far, just add zero!
Examples:
SET
#yournumber1="1.500",
#yournumber2="23.030",
#yournumber3="2.000",
#yournumber4="4.450"
;
SELECT
(#yournumber1+0),
(#yournumber2+0),
(#yournumber3+0),
(#yournumber4+0)
;
+------------------+------------------+------------------+------------------+
| (#yournumber1+0) | (#yournumber2+0) | (#yournumber3+0) | (#yournumber4+0) |
+------------------+------------------+------------------+------------------+
| 1.5 | 23.03 | 2 | 4.45 |
+------------------+------------------+------------------+------------------+
1 row in set (0.00 sec)
If the column your value comes from is DECIMAL or NUMERIC type, then cast it to string first to make sure the conversion takes place...ex:
SELECT (CAST(`column_name` AS CHAR)+0) FROM `table_name`;
For a shorter way, just use any built-in string function to do the cast:
SELECT TRIM(`column_name`)+0 FROM `table_name`;

EDIT: I would use the answer below by Christopher McGowan instead - adding 0 to the value, which is better, instead.
It's important to check there is actually a decimal point if doing trimming.
So I think you'd want to use:
SELECT TRIM(TRAILING '.' FROM TRIM(TRAILING '0' from yourfield)) AS yourfield
FROM yourtable
WHERE yourfield LIKE '%.%'

this worked for me.. round the field to 2 decimal places and then trim any trailing zeros
So that 2.10 is 2.1
SELECT trim(round(FIELDNAME,2))+0
FROM tbl_name
....

To remove trailing zeros from a DECIMAL/NUMERIC or string type column, you can simply cast the value to DOUBLE, e.g.:
SELECT CAST(mycol AS DOUBLE) from mytable;
or
SELECT mycol + 0E0 FROM mytable;
In fact, the "cast to char and add zero" trick mentioned in other answers does the same, but in a more indirect (and likely less efficient) way, e.g:
SELECT CAST(mycol AS CHAR)+0 FROM mytable; -- converts to string, then to number
SELECT TRIM(mycol)+0 FROM mytable; -- ditto

Please use below function , it will take care of number having zero without decimal places i.e 150 etc....
SET #saved_cs_client = ##character_set_client;
SET character_set_client = utf8;
DELIMITER $$
USE `mydbname`$$
DROP FUNCTION IF EXISTS `FN_STRIP_TRAILING_ZER0`$$
CREATE DEFINER=`mydbuser`#`%` FUNCTION `FN_STRIP_TRAILING_ZER0`(tNumber DECIMAL(10,7)) RETURNS VARCHAR(20) CHARSET utf8
BEGIN
DECLARE strBuff VARCHAR(20);
DECLARE cnt NUMERIC(2);
DECLARE tString VARCHAR(20);
SELECT CAST(tNumber AS CHAR) INTO tString;
SELECT LOCATE('.',tString) INTO cnt;
IF cnt > 0 THEN
SELECT TRIM(TRAILING '.' FROM TRIM(TRAILING '0' FROM tString)) INTO strBuff;
ELSE
SET strBuff = tString;
END IF;
RETURN strBuff;
END$$
DELIMITER ;
SET character_set_client = #saved_cs_client;
Addendum:
Typically to call this would involve:
SELECT FN_STRIP_TRAILING_ZER0(1.5);

The best solution I found is to cast your round value to FLOAT:
SELECT CAST(ROUND(1.2345984372, 2) AS FLOAT)

Here's what worked for me:
SINGLE COLUMN:
SELECT TRIM(column_name)+0 AS column_name FROM table_name;
MULTIPLE COLUMNS:
SELECT
TRIM(column1)+0 AS column1,
TRIM(column2)+0 AS column2,
TRIM(column3)+0 AS column3,
FROM table_name;

Taking forward the answer provided by #fooquency, if the column is already declared as a DECIMAL with a non-zero value for D in DECIMAL(M, D), we do not need to perform the WHERE condition
WHERE yourfield LIKE '%.%'
as the values in the column will always contain D digits after the decimal dot (.)

If you are using PHP as the scripting language you may use the following:
$var = (float)$var_having_extra_0; // $var = (float) 17.5000
Or use the PHP floatval function:
$var = floatval($var_having_extra_0); // $var = floatval(17.5000)

Using ROUND or CEILING, in the query you just have to type:
SELECT ROUND(2/50)
or
SELECT CEILING(2/50)

I had a similar problem in a situation where I could not modify the code nor the SQL query, but I was allowed to modify the database structure. So I changed the column format from DECIMAL to FLOAT and it solved my problem.

SELECT TRIM(TRAILING '.' FROM TRIM(TRAILING '0' from yourfield)) AS yourfield
FROM yourtable
WHERE yourfield LIKE '%.%'
or
SELECT TRIM(TRAILING '.' FROM TRIM(TRAILING '0' from yourfield)) AS yourfield
FROM yourtable
WHERE instr(yourfield,'.') != 0
work ok but require a "where" clause.
I think the best solution is probably:
SELECT TRIM(TRAILING '.' FROM TRIM(TRAILING '0' FROM ROUND(yourfield,3)))
FROM yourtable
as it doesn't require a "where" clause, doesn't require any special code,
and also lets you set the maximum precision of the number upfront.

Taking fragments of the others answers in this page I came to this conclusion:
SELECT ( IF(
myfield LIKE '%.%',
TRIM(TRAILING '.' FROM TRIM(TRAILING '0' FROM myfield)),
myfield
) ) FROM mytable
Cheers

SELECT TRIM(TRAILING '0' FROM yourodds)
FROM ...
Docs for the TRIM function.

Related

trigger validation using regular expression not working for newline character

I am trying to validate inserts using a mysql-trigger. The inserts in col1 should be only numerical. It is NOT an option to define col1 as an integer in the first place. However, the validation fails if there is a newline character at the end.
Heres the table
CREATE TABLE testTable(col1 varchar(20), col2 int);
and here the trigger validator
DELIMITER $$
CREATE TRIGGER check_numeric BEFORE INSERT ON testTable
FOR EACH ROW
BEGIN
IF (NEW.col1 REGEXP '^[0-9]+$') = 0 THEN
SIGNAL SQLSTATE '12345' SET MESSAGE_TEXT='non-numerical';
END IF;
END $$
If I try to insert a string including a newline character at the end this passes the validation, although it shouldn't in my opinion as the newline character is not numeric.
INSERT INTO testTable values('323423\n', 12);
Does anybody have an idea what I am missing here?
Another option is to search for anything that is not a digit instead, this will return 1 if any character is not a digit: REGEXP '[^[:digit:]]'
So the IF clause would be
IF (NEW.col1 REGEXP '[^[:digit:]]') = 1 THEN ...
Of course you could write [^0-9] instead of [:digit:] if you don't want to use the character class
can you check in this way
IF NEW.col1 REGEXP '^[0-9]+$' AND NEW.col1 NOT REGEXP '\n' THEN
with w as
(select '1234' c1 from dual union all
select '1234\n' from dual)
select * from w
where c1 REGEXP '^[0-9]+$' AND c1 NOT REGEXP "\n";
Result : 1234
Working Fiddle

Mysql: replace leading zeroes inside text

I wish to replace cca 3 500 000 values in Mysql Table. Each value is string in the form of AB00123012 and I wish to remove leading zeroes after letters - i.e. get AB123012 (zeroes inside number should be kept).
The value has always exactly 10 characters.
Since Mysql does not allow replace by regex, I have used following function:
DELIMITER $$
CREATE FUNCTION fn_RawRingNumber (rn CHAR(10))
RETURNS CHAR(10) DETERMINISTIC
BEGIN
DECLARE newrn CHAR(10);
DECLARE pos INT(8);
DECLARE letters CHAR(2);
DECLARE nr CHAR(8);
IF (CHAR_LENGTH(rn) = 10) THEN
SET pos = (SELECT POSITION('0' IN rn));
SET letters = (SELECT SUBSTRING_INDEX(rn, '0', 1));
SET nr = (SELECT TRIM(LEADING '0' FROM SUBSTRING(rn,pos)));
SET newrn = (SELECT CONCAT(letters, nr));
ELSE
SET newrn = rn;
END IF;
RETURN newrn;
END$$
DELIMITER ;
While this works, it is rather slow and I am wondering, if there is not a better way to do this?
If you can afford to take your site offline for a few minutes, the fastest way would be to dump, process and re import. Since the current operation makes queries/inserts on that table pretty slow, so you are probably better off with a dump/process/import anyway.
Step 1 dump.
SELECT INTO OUTFILE is your friend here
Step 2 process
Use your favourite programming language or if you are lucky to be on linux, something like sed or even cut. If you need help with the regex post a comment.
Step 3 reimport
After clearing out the table. Do a LOAD DATA INFILE.
these three steps should all be reasonably quick. Specially if you have a n index on that column.
Try this
Note: I not tested this with many rows and don't know how this is efficient.
Also, if this is fast, please before using this, think all possible variations, which may occurs with your string, may be I missed some variants, not sure 100%.
select case
when INSTR(col, '0') = 2 then concat( substr(col, 1, 1), substr(col, 2) * 1)
when INSTR(col, '0') = 3 and substr(col, 2, 1) not in('1','2','3','4','5','6','7','8','9') then concat( substr(col, 1, 2), substr(col, 3) * 1)
else col
end
from (
select 'AB00123012' as col union all
select 'A010000123' as col union all
select 'A1000000124' as col union all
select 'A0000000124' as col union all
select '.E00086425' as col
) t

Replace in SQL Server 2008

I have a column A in a table called T. The column is of type nvarchar(255).
There is a trigger on this table that updates the values in column A to a column B in table B. The column B is of type float.
Suppose if there is value 35.1 % in column A, I want to strip off the % and update only 35.1 in column B. It is not necessary that there should be a % symbol for the value in column A.
How do I do this in SQL Server 2008? Any ideas and suggestions are much appreciated!
You may try to use the following query:
update B
set B.colB = cast(REPLACE(A.colA, '%', '') as float)
from A
where B.idB = A.idA
select replace('35.3 %','%','') or select replace('35.3 ','%','') will both return 35.3; just change your query accordingly; something like:
update tableb
set b=replace(valuefromcola,'%','')
where condition
If you want to get only numbers in a string try this function:
CREATE Function [dbo].[GetNumbersFromString](#Temp VarChar(1000))
Returns VarChar(1000)
AS
Begin
While PatIndex('%[^0-9]%', #Temp) > 0
Set #Temp = Stuff(#Temp, PatIndex('%[^0-9]%', #Temp), 1, '')
Return #TEmp
End
You should put this inside your trigger. Please note that you'll need to modify the function to accept the . and , characters (due to those being valid in numbers) =-)
--trim trailing non-alphanumeric chars
DECLARE #input nvarchar(4000)
SET #input = ',,, a word $$$'
SELECT REVERSE(SUBSTRING(REVERSE(#input), PATINDEX('%[a-zA-Z0-9]%', REVERSE(#input)), LEN(#input)))
update B
set B.colB = cast(REPLACE(A.colA, '%', '') as float)
from A
where B.idB = A.idA

MySQL find_in_set with multiple search string

I find that find_in_set only search by a single string :-
find_in_set('a', 'a,b,c,d')
In the above example, 'a' is the only string used for search.
Is there any way to use find_in_set kind of functionality and search by multiple strings, like :-
find_in_set('a,b,c', 'a,b,c,d')
In the above example, I want to search by three strings 'a,b,c'.
One way I see is using OR
find_in_set('a', 'a,b,c,d') OR find_in_set('b', 'a,b,c,d') OR find_in_set('b', 'a,b,c,d')
Is there any other way than this?
there is no native function to do it, but you can achieve your aim using following trick
WHERE CONCAT(",", `setcolumn`, ",") REGEXP ",(val1|val2|val3),"
The MySQL function find_in_set() can search only for one string in a set of strings.
The first argument is a string, so there is no way to make it parse your comma separated string into strings (you can't use commas in SET elements at all!). The second argument is a SET, which in turn is represented by a comma separated string hence your wish to find_in_set('a,b,c', 'a,b,c,d') which works fine, but it surely can't find a string 'a,b,c' in any SET by definition - it contains commas.
You can also use this custom function
CREATE FUNCTION SPLIT_STR(
x VARCHAR(255),
delim VARCHAR(12),
pos INT
)
RETURNS VARCHAR(255)
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos),
LENGTH(SUBSTRING_INDEX(x, delim, pos -1)) + 1),
delim, '');
DELIMITER $$
CREATE FUNCTION `FIND_SET_EQUALS`(`s1` VARCHAR(200), `s2` VARCHAR(200))
RETURNS TINYINT(1)
LANGUAGE SQL
BEGIN
DECLARE a INT Default 0 ;
DECLARE isEquals TINYINT(1) Default 0 ;
DECLARE str VARCHAR(255);
IF s1 IS NOT NULL AND s2 IS NOT NULL THEN
simple_loop: LOOP
SET a=a+1;
SET str= SPLIT_STR(s2,",",a);
IF str='' THEN
LEAVE simple_loop;
END IF;
#Do check is in set
IF FIND_IN_SET(str, s1)=0 THEN
SET isEquals=0;
LEAVE simple_loop;
END IF;
SET isEquals=1;
END LOOP simple_loop;
END IF;
RETURN isEquals;
END;
$$
DELIMITER ;
SELECT FIND_SET_EQUALS('a,c,b', 'a,b,c')- 1
SELECT FIND_SET_EQUALS('a,c', 'a,b,c')- 0
SELECT FIND_SET_EQUALS(null, 'a,b,c')- 0
Wow, I'm surprised no one ever mentioned this here.In a nutshell, If you know the order of your members, then just query in a single bitwise operation.
SELECT * FROM example_table WHERE (example_set & mbits) = mbits;
Explanation:
If we had a set that has members in this order: "HTML", "CSS", "PHP", "JS"... etc.
That's how they're interpreted in MySQL:
"HTML" = 0001 = 1
"CSS" = 0010 = 2
"PHP" = 0100 = 4
"JS" = 1000 = 16
So for example, if you want to query all rows that have "HTML" and "CSS" in their sets, then you'll write
SELECT * FROM example_table WHERE (example_set & 3) = 3;
Because 0011 is 3 which is both 0001 "HTML" and 0010 "CSS".
Your sets can still be queried using the other methods like REGEXP , LIKE, FIND_IN_SET(), and so on. Use whatever you need.
Amazing answer by #Pavel Perminov! - And also nice comment by #doru for dynamically check..
From there what I have made for PHP code CONCAT(',','" . $country_lang_id . "', ',') REGEXP CONCAT(',(', REPLACE(YourColumnName, ',', '|'), '),') this below query may be useful for someone who is looking for ready code for PHP.
$country_lang_id = "1,2";
$sql = "select a.* from tablename a where CONCAT(',','" . $country_lang_id . "', ',') REGEXP CONCAT(',(', REPLACE(a.country_lang_id, ',', '|'), '),') ";
You can also use the like command for instance:
where setcolumn like '%a,b%'
or
where 'a,b,c,d' like '%b,c%'
which might work in some situations.
you can use in to find match values from two values
SELECT * FROM table WHERE myvals in (a,b,c,d)

how to trim leading zeros from alphanumeric text in mysql function

What mysql functions are there (if any) to trim leading zeros from an alphanumeric text field?
Field with value "00345ABC" would need to return "345ABC".
You are looking for the trim() function.
Alright, here is your example
SELECT TRIM(LEADING '0' FROM myfield) FROM table
TIP:
If your values are purely numerical, you can also use simple casting, e.g.
SELECT * FROM my_table WHERE accountid = '00322994' * 1
will actually convert into
SELECT * FROM my_table WHERE accountid = 322994
which is sufficient solution in many cases and also I believe is performance more effective. (warning - value type changes from STRING to INT/FLOAT).
In some situations, using some casting function might be also a way to go:
http://dev.mysql.com/doc/refman/5.0/en/cast-functions.html
If you want to update one entire column of a table, you can use
USE database_name;
UPDATE `table_name` SET `field` = TRIM(LEADING '0' FROM `field`) WHERE `field` LIKE '0%';
I believe you'd be best off with this:
SELECT TRIM(LEADING '0' FROM myField)
SELECT TRIM(LEADING '0' FROM *columnName*) FROM *tableName* ;
This also work correctly
just remove space between TRIM ( LEADING
use
SELECT * FROM my_table WHERE TRIM(LEADING '0' FROM accountid ) = '00322994'
simply perfect:
SELECT TRIM(LEADING '0' FROM myfield) FROM table
TRIM will allow you to remove the trailing, leading or all characters. Some examples on the use of the TRIM function in MySQL:
select trim(myfield) from (select ' test' myfield) t;
>> 'test'
select trim('0' from myfield) from (select '000000123000' myfield) t;
>> '123'
select trim(both '0' from myfield) from (select '000000123000' myfield) t;
>> '123'
select trim(leading '0' from myfield) from (select '000000123000' myfield) t;
>> '123000'
select trim(trailing '0' from myfield) from (select '000000123000' myfield) t;
>> '000000123'
If you want to remove only a select amount of leading/trailing characters, look into the LEFT/RIGHT functions, with combination of the LEN and INSTR functions