MySQL Remove Trailing Zero - mysql

Is there a built-in function in MySQL the removes trailing zeros on the right?
I have samples and i want my output to be like this:
1.0 ==> 1
1.50 ==> 1.5
10.030 ==> 10.03
0.50 ==> 0.5
0.0 ==> 0

Easiest way by far, just add zero!
Examples:
SET
#yournumber1="1.0",
#yournumber2="1.50",
#yournumber3="10.030",
#yournumber4="0.50",
#yournumber5="0.0"
;
SELECT
(#yournumber1+0),
(#yournumber2+0),
(#yournumber3+0),
(#yournumber4+0),
(#yournumber5+0)
;
+------------------+------------------+------------------+------------------+------------------+
| (#yournumber1+0) | (#yournumber2+0) | (#yournumber3+0) | (#yournumber4+0) | (#yournumber5+0) |
+------------------+------------------+------------------+------------------+------------------+
| 1 | 1.5 | 10.03 | 0.5 | 0 |
+------------------+------------------+------------------+------------------+------------------+
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`;

it solves my problem using this:
(TRIM(TRAILING '.' FROM(CAST(TRIM(TRAILING '0' FROM setpoint)AS char)))) AS setpoint
example:
mysql> SELECT testid, designationid, test, measure,
(TRIM(TRAILING '.' FROM(CAST(TRIM(TRAILING '0' FROM setpoint)AS char)))) AS setpoint,
(TRIM(TRAILING '.' FROM(CAST(TRIM(TRAILING '0' FROM tmin)AS char)))) AS tmin,
(TRIM(TRAILING '.' FROM(CAST(TRIM(TRAILING '0' FROM tmax)AS char)))) AS tmax,
FROM tests

This is my method:
SELECT TRIM(TRAILING '.' FROM TRIM(TRAILING '0' FROM `table`.`column`)) FROM table

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.

Related

How do you store and mutate a bitmap/bitset using MySQL?

I want to create a table column that stores a 500 byte bitmap (500 bytes * 8 bits per byte = 4000 bits) and do operations to mutate bits (set to 1 or 0) at certain indexes in the bitmap.
However, the documentation page on bitmaps is mostly empty leaving me with the raw bit functions as the only guide. How do you create, count, read, and mutate a bitmap as a column type in MySQL?
Using bin and lpad you can print a 64 bit number out as a binary string.
LPAD(BIN(34), 64, '0')
0000000000000000000000000000000000000000000000000000000000100010
However, how do you print out a binary/blob/varbinary string that might be 4000 bits long?
(Note: not talking about bitmap indexes)
First, upgrade to MySQL 8.0. This won't work on earlier versions of MySQL.
You should use BINARY, VARBINARY, or BLOB, depending on the length of the bitfields you want to store.
mysql> create table mytable ( bits binary(500) );
ERROR 1074 (42000): Column length too big for column 'bits' (max = 255); use BLOB or TEXT instead
mysql> create table mytable ( bits blob(500) );
Query OK, 0 rows affected (0.02 sec)
Use UNHEX() to form bitfields from hexadecimal strings. It's too difficult to work with binary bytes directly.
mysql> insert into mytable set bits = unhex(repeat('00', 500));
Query OK, 1 row affected (0.00 sec)
You can use bitwise operators like |, &, ^, and ~ with bitfields. But the strings must be the same length!
mysql> update mytable set bits = bits | b'01000';
ERROR 3513 (HY000): Binary operands of bitwise operators must be of equal length
It's inconvenient, but you must form strings that are the right length using CONCAT():
mysql> update mytable set bits = bits | unhex(concat(repeat('00', 498), 'ffff'));
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
Reading a bit string (I have shortened it for this display):
mysql> select hex(bits) from mytable\G
*************************** 1. row ***************************
hex(bits): 000...000FFFF
The BIT_COUNT() function works:
mysql> select bit_count(bits) from mytable;
+-----------------+
| bit_count(bits) |
+-----------------+
| 16 |
+-----------------+
mysql> select bit_count(~bits) from mytable;
+------------------+
| bit_count(~bits) |
+------------------+
| 3984 |
+------------------+
By this time, you should sit back and think about whether SQL is the best tool for this task, even with the features of MySQL 8.0. You will find it more flexible and powerful to do bitwise work in most other programming languages.
Use BLOB as data type and write a function wich will:
extract the byte which needs to be updated
change the bit in the byte
insert the changed byte into the blob at the original position
Here is one implementation:
delimiter //
create function set_bit(b blob, pos int, val int) returns blob reads sql data
comment 'changes the bit at position <pos> (0: right most bit) to <val> in the blob <b>'
begin
declare len int; -- byte length of the blob
declare byte_pos int; -- position of the affected byte (1: left most byte)
declare bit_pos int; -- position within the affected byte (0: right most bit)
declare byte_val int; -- value of the affected byte
set len = length(b);
set byte_pos = len - (pos div 8);
set bit_pos = pos mod 8;
set byte_val = ord(substring(b, byte_pos, 1)); -- read the byte
set byte_val = byte_val & (~(1 << bit_pos)); -- set the bit to 0
set byte_val = byte_val | (val << bit_pos); -- set the bit to <val>
return insert(b, byte_pos, 1, char(byte_val)); -- replace the byte and return
end //
delimiter ;
A simple test:
create table test(id int, b blob);
insert into test(id, b) select 1, 0x000000;
insert into test(id, b) select 2, 0xffffff;
We have two blob bitmasks (3 bytes each) - One full of zeros and one full of ones. In both we set the bit at position 10 (11th bit from right) to 1 and the bit at position 11 (12th bit from right) to 0.
update test set b = set_bit(b, 10, 1);
update test set b = set_bit(b, 11, 0);
select id, hex(b), to_base2(b) from test;
Result:
| id | hex(b) | to_base2(b) |
| --- | ------ | -------------------------- |
| 1 | 000400 | 00000000 00000100 00000000 |
| 2 | FFF7FF | 11111111 11110111 11111111 |
View on DB Fiddle
Note: to_base2() is a custom function that returns a string with a bit representation of a BLOB and is only used for presentation purpose.
This works for MySQL 5.x as well as for 8.0.
It is possible to implement it inline in a single expression (without the need of a function) - But that is rather unreadable:
update test t
cross join (select 10 as pos, 1 as val) i -- input
set t.b = insert(
t.b,
length(t.b) - (i.pos div 8),
1,
char(ord(
substring(t.b, length(t.b) - (i.pos div 8), 1))
& ~(1 << (i.pos mod 8))
| (i.val << (i.pos mod 8)
))
);
View on DB Fiddle
In MySQL 8.0 it's a bit simpler, since we don't need to extract the byte and can use bit operations on blobs. But we need to make sure, that the oprerands are of the same length:
update test t
cross join (select 10 as pos, 1 as val) i -- input
set t.b = t.b
& (~(concat(repeat(0x00,length(t.b)-1),char(1)) << i.pos))
| (concat(repeat(0x00,length(t.b)-1),char(i.val)) << i.pos)
View on DB Fiddle
Another way:
update test t
cross join (select 10 as pos, 1 as val) i -- input
set t.b =
case when i.val = 1
then t.b | concat(repeat(0x00,length(t.b)-1),char(1)) << i.pos
else t.b & ~(concat(repeat(0x00,length(t.b)-1),char(1)) << i.pos)
end
View on DB Fiddle

MySQL Question - I want to eliminate all text within any parenthesis

Just checking to see if any of you would have a solution for this – from the below text like this I want to eliminate all text within any parenthesis.
Input –
PAY - addition,FILES (aaaaaaaaaaaaaa/bbbbbbbbbbbs i.e. ssss,ffff – i.e. cccccc),DED (ppppppp, llllll, fffff gggg),LOSS (ddddd, hhhhhh – i.e.),F TO G ( “F” is switching to “G”)
Output –
PAY - addition,FILES,DED,LOSS,F TO G
If you are running MySQL 8.0, you can do this with regexp_replace():
regexp_replace(mytext, '\\([^)]*\\)', '')
This works as long as there are no nested parentheses in the expression (which is consistent with your sample data).
Demo on DB Fiddle:
select regexp_replace(
'PAY - addition,FILES (aaaaaaaaaaaaaa/bbbbbbbbbbbs i.e. ssss,ffff – i.e. cccccc),DED (ppppppp, llllll, fffff gggg),LOSS (ddddd, hhhhhh – i.e.),F TO G ( “F” is switching to “G”)',
'\\([^)]*\\)',
''
) val
| val |
| :--------------------------------------- |
| PAY - addition,FILES ,DED ,LOSS ,F TO G |
Another on for MYSQL8.0:
SET #input:="PAY - addition,FILES (aaaaaaaaaaaaaa/bbbbbbbbbbbs i.e. ssss,ffff – i.e. cccccc),DED (ppppppp, llllll, fffff gggg),LOSS (ddddd, hhhhhh – i.e.),F TO G ( “F” is switching to “G”)";
with recursive cte as (
select
0 i,
#input as text
union all
select
i+1,
CASE WHEN instr(text,'(') >0 AND instr(text,')')>instr(text,'(') THEN REPLACE(text, substring(text,instr(text,'('),instr(text,')')-instr(text,'(')+1), '') ELSE '' END
from cte
where i<10
) select text from cte where text<>'' order by i desc limit 1;
output:
+------------------------------------------+
| text |
+------------------------------------------+
| PAY - addition,FILES ,DED ,LOSS ,F TO G |
+------------------------------------------+
1 row in set (0.00 sec)

How to convert from varchar to float and ignore non-numeric characters?

I am trying to convert a column from varchar(500) to float in my sql.
My code currently looks like this:
select distinct(customer_id), cast(val_amt as float) from(
select prsn_real_gid, vital_nam, vital_performed_date,
case when val_amt ~'^[0-9]+' then val_amt else null end as val_amt from my_table);
but I get the following error message
[Amazon](500310) Invalid operation: Invalid digit, Value 'X', Pos 2, Type: Double
Details:
-----------------------------------------------
error: Invalid digit, Value 'X', Pos 2, Type: Double
code: 1207
context: 1.XYXY04
query: 4147
location: :0
process: query0_118_4147 [pid=0]
-----------------------------------------------;
1 statement failed.
My data for example looks like this:
customer_id | val_amt
111 | 23.45
112 | 21
113 | x
114 | /
115 |
It has alpha characters, symbols, and nulls. I just want the numbers including the decimals.
In SQL Server you would use try_cast():
select distinct customer_id, try_cast(val_amt as float)
from my_table;
where try_cast(val_amt as float) is not null;
try this using isnumeric
select customer_id, case when isnumeric([val_amt])=0
enter code herethen 0 else cast([val_amt] as float) end from my_table
Sometimes the Cast gives me problems. Even Try_Cast(). This may be good for what you need. EDIT: You changed from SQLServer to MySQL. Adjusted for MySQL
select distinct customer_id, convert(`val_amt`, float(2,2))
from my_table
where convert(`val_amt`,float(2,2)) is not null;

Mysql - round half down or half up

Is there a way to specify if we want to round a field value 4.485 to 4.48(half down) or to 4.49 (half up) in a sql query with MySql?
Thanks
Even if the question is years old, I had the same problem and found a different solution I'd like to share.
Here it is: using a conditional function you explicitly decide which way you want to round when the last decimal is 5.
For instance, if you want to round half up with 2 decimals:
SELECT IF ((TRUNCATE(mynumber*1000,0) mod 5) = 0,CEIL(mynumber*100)/100,ROUND(mynumber,2)) as value FROM mytable
You can use FLOOR function instead of CEIL if you want to round half down; if you want a different number of decimals, say n, you change the multiplier inside the TRUNCATE call (10^n+1) and you pass it to the ROUND function.
SELECT IF ((TRUNCATE(mynumber*([10^*n+1*]),0) mod 5) = 0,[CEIL|FLOOR](mynumber*100)/100,ROUND(mynumber,[*n*])) as value FROM mytable
Based on the official MySQL documentation there is no way to specify a rounding strategy. By default, ROUND uses the “round half up” rule for exact-value numbers.
However, I needed a function that behaves like java.math.BigDecimal with java.math.RoundingMode.HALF_DOWN mode. So the only solution that I found was to create my own function.
The code (tested in MySQL 5.7)
DELIMITER //
DROP FUNCTION IF EXISTS roundHalfDown //
CREATE FUNCTION roundHalfDown (
numberToRound DECIMAL(25,15),
roundingPrecision TINYINT(2)
)
RETURNS DECIMAL(25,15)
BEGIN
DECLARE digitPosition TINYINT (2) UNSIGNED DEFAULT 0;
DECLARE digitToRound TINYINT (2) DEFAULT -1;
DECLARE roundedNumber DECIMAL(20,6) DEFAULT 0;
SET digitPosition = INSTR(numberToRound, '.');
IF (roundingPrecision < 0) THEN
SET digitPosition = digitPosition + roundingPrecision;
ELSE
SET digitPosition = digitPosition + roundingPrecision + 1;
END IF;
IF (digitPosition > 0
AND digitPosition <= CHAR_LENGTH(numberToRound)
) THEN
SET digitToRound = CAST(
SUBSTR(
numberToRound,
digitPosition,
1
) AS UNSIGNED
);
SET digitPosition = digitPosition - 1;
END IF;
IF (digitToRound > -1) THEN
IF (digitToRound > 5) THEN
SET roundedNumber = ROUND(numberToRound, roundingPrecision);
ELSEIF (digitToRound = 5 AND CAST(
SUBSTR(
REPLACE(numberToRound, '.', ''),
digitPosition + 1
) AS UNSIGNED) > 0) THEN
SET roundedNumber = ROUND(numberToRound, roundingPrecision);
ELSE
SET roundedNumber = TRUNCATE(numberToRound, roundingPrecision);
END IF;
ELSEIF (roundingPrecision > 0) THEN
SET roundedNumber = numberToRound;
END IF;
RETURN roundedNumber;
END //
DELIMITER ;
Test Cases
SELECT roundHalfDown(1.541, 2); #1.54
SELECT roundHalfDown(1.545, 2); #1.54
SELECT roundHalfDown(1.5451, 2); #1.55
SELECT roundHalfDown(1.54500001, 2); #1.55
SELECT roundHalfDown(1.54499999, 2); #1.54
SELECT roundHalfDown(-1.545, 2); #-1.54
SELECT roundHalfDown(-1.5451, 2); #-1.55
SELECT roundHalfDown(555, 0); #555
SELECT roundHalfDown(1000999, -1); #1001000
SELECT roundHalfDown(1000999, -2); #1001000
SELECT roundHalfDown(1000999, -3); #1001000
SELECT roundHalfDown(1000999, -4); #1000000
I used this answer from another Stack Overflow question, but I changed it a bit for my specific case.
Andrea Pegoretti's answer is almost correct, however it will apply when it's a 5 or a 0 instead of just a 5.
My fix (for round down):
SELECT IF (SUBSTR(TRUNCATE(CEIL(mynumber*1000),0),-1) = 5,FLOOR(mynumber*100)/100,ROUND(mynumber, 2))) AS value FROM mytable
The accepted answer of this post offers a good solution :
MySQL - How can I always round up decimals?
i.e multiply by 10^n where n is the decimal place you want to round to then call ceil to round up or floor to round down and divide by 10^n.
You can use the CEIL (or CEILING) and the FLOOR functions to round up/round down.
For example:
CEIL(4.485 * 100) / 100 will return 4.49
FLOOR(4.485 * 100) / 100 will return 4.48
I have the same question and I try all kind of custom function to emulate the functionality of PHP with a round up and down, but after a while, I figured out that MySQL produces different results using float and doubles fields.
Here my test.
mysql> describe test_redondeo;
+----------------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+--------------+------+-----+---------+-------+
| columna_double | double(15,3) | YES | | NULL | |
| columna_float | float(9,3) | YES | | NULL | |
| id | int(11) | NO | PRI | NULL | |
+----------------+--------------+------+-----+---------+-------+
3 rows in set (0.01 sec)
In fields type double, round function truncate, but in float round up.
mysql> select columna_double, columna_float, round ( columna_double, 2) as round_double, round ( columna_float, 2) as round_float from test_redondeo;
+----------------+---------------+--------------+-------------+
| columna_double | columna_float | round_double | round_float |
+----------------+---------------+--------------+-------------+
| 902.025 | 902.025 | 902.02 | 902.03 |
+----------------+---------------+--------------+-------------+
1 row in set (0.00 sec)
If you made a custom function for round a number using round() in any way, please pay attention to type of field.
Hope this test helps you.
According to Mysql docs,
For exact-value numbers, ROUND() uses the “round half up” rule
I had also a situation, where I was wondering why is Mysql rounding(1) 74,447 to 74,4. It was because it was in fact an endless long decimal, a approximate-value number, and not a exact-value number. The solution for me was, that I had to use ROUND() 3x like this: ROUND(ROUND(ROUND(value, 3), 2), 1). The first rounding makes sure that it's not a approximate-value number any more (where Mysql uses the “round to nearest even” rule), but a exact-value number, a decimal 3 number.

Replace 44 to 0 in MYSQL?

How to replace first 44 digits to 0 in MySQL?
For example:
4476384424131 to 076384424131
Using character types and substring functions, you can simply cut off the initial '44' and replace it with a zero concatenated back on.
UPDATE tbl
SET num = CONCAT('0', SUBSTR(num, 3))
WHERE LEFT(num, 2) = '44'
(Edit: fixed the WHERE clause to use LEFT() instead of SUBSTR())
mysql> SELECT CONCAT('0', SUBSTR(4476384424131, 3));
+-----------------------------------------+
| CONCAT('0', SUBSTR(4476384424131, 3)) |
+-----------------------------------------+
| 076384424131 |
+-----------------------------------------+