Remove trailing zeros only from int numbers - mysql

I have decimal column in db and trying to remove trailing zeros only from int numbers (100, 200, 300) with query in php. I tried with trim/cast functions but 10.50 turned 10.5.
SELECT TRIM(TRAILING '0' FROM `my_column`) FROM `mytable`
200.00
10.50
247.09
would display as
200
10.50
247.09

Use a case expression to determine if a number is an integer using ceil() and if it is format with zero decimals, if not with 2 decimals.
SELECT
CASE WHEN ceil(n) = n THEN format(n, 0) ELSE format(n, 2) END
FROM (
SELECT
1234.5 AS n
UNION ALL
SELECT
1234
) d

Related

MySQL format number with unknown number of decimal places

In MySQL, I only want to add thousand separator in the number like 1234.23234, 242343.345345464, 232423.22 and format to "1,234.23234", "242,343.345345464", "232,423.22", use format function need to specify the number of decimals, is there any other function can format the number with unknown number of decimal places? for 1234.23234, I do not want to get the result like 1234.2323400000 or 1234.23, just want to get 1,234.23234.
As suggested split the string drop the trailing zeros format the number before the decimal point and concat taking into account the possibility of no decimals being present at all for example
set #a = 1234.56;
select
case when instr(#a,'.') > 0 then
concat(
format(substring_index(#a,'.',1),'###,###,###'),
'.',
trim(trailing '0' from substring_index(#a,'.',-1))
)
else
format (#a,'###,###,###')
end formatted
MySQL doesn't seem to have such feature. You'll probably need to write a custom function based on FORMAT() plus some string manipulation to remove trailing zeroes after the comma, for example using REGEXP_REPLACE(). The default locale used in FORMAT() is en_US, which seems to be the one you want, so you can omit it or provide your own should you need a different locale.
WITH sample_data (sample_number) AS (
SELECT NULL
UNION ALL SELECT 0
UNION ALL SELECT 0.00001
UNION ALL SELECT 100.01
UNION ALL SELECT 100.0102
UNION ALL SELECT 100.012300456
UNION ALL SELECT 1000
UNION ALL SELECT 123456789.87654321
UNION ALL SELECT -56500.333
)
SELECT
sample_number,
REGEXP_REPLACE(
FORMAT(sample_number, 999),
'(\.\\d*[1-9])(0+$)|(\.0+$)',
'$1'
) AS USA,
-- Replace \. with , for locales that use comma as decimal separator:
REGEXP_REPLACE(
FORMAT(sample_number, 999, 'de_DE'),
'(,\\d*[1-9])(0+$)|(,0+$)',
'$1'
) AS Germany
FROM sample_data;
sample_number
USA
Germany
NULL
NULL
NULL
0.000000000
0
0
0.000010000
0.00001
0,00001
100.010000000
100.01
100,01
100.010200000
100.0102
100,0102
100.012300456
100.012300456
100,012300456
1000.000000000
1,000
1.000
123456789.876543210
123,456,789.87654321
123.456.789,87654321
-56500.333000000
-56,500.333
-56.500,333
Fiddle

losing decimal precision in string filed when updating MySQL table

I have a filed with varchar(255) data type. when I run this query :
update sample_tbl
set in_order_real = in_order_real + 21.215541764099030466
where id = 15
it removes extra decimals.
for example in_order_real number is 0 and when I run this query it keeps only some decimals and round up while it is a string field. how can i fix this issue?
You must cast your string value to DECIMAL with proper precision.
CREATE TABLE sample_tbl (id INT, in_order_real VARCHAR(255))
SELECT 15 id, 1.23 in_order_real
UNION ALL
SELECT 16, 1.23;
SELECT * FROM sample_tbl;
id
in_order_real
15
1.23
16
1.23
update sample_tbl
set in_order_real = in_order_real + 21.215541764099030466
where id = 15;
update sample_tbl
set in_order_real = CAST(in_order_real AS DECIMAL(30, 18)) + 21.215541764099030466
where id = 16;
SELECT * FROM sample_tbl;
id
in_order_real
15
22.44554176409903
16
22.445541764099030466
db<>fiddle here
If you don't know actual decimal digits amount then use maximal possible value. Additionally you may trim trailing zeros in the result.
FLOAT holds 24 significant bits -- about 7 decimal digits of significance.
DOUBLE: 53 and 16
So, putting 21.215541764099030466 into a FLOAT will garble the digits after about 7 digits: ~21.21554. For DOUBLE: ~21.21554176409903
Can't do arithmetic in VARCHARs; it is converted either to DOUBLE or DECIMAL.
Where do your numbers come from? For money, use DECIMAL(..., 2); for sensor readings, use FLOAT.

Compare two Alphanumerical mysql columns (Find postcode district between range)

I have a mysql database that contains a range of postcode district ranges.
I am trying to find the row that matches the given district, in this example 'SY18'.
I have mysql query below, but it returns both the values in the table because the fields are alphanumeric.
SELECT rate FROM table WHERE district_from <= 'SY18' AND district_to >= 'SY18'
Table example
id district_from district_to rate
1 SY1 SY9 10
2 SY16 SY22 20
3 AL1 AL99 37
4 B1 B99 37
5 BB1 BB99 37
6 CB1 CB99 40
How do I return only correct results?
You can use SUBSTR to skip first characters of the string and then +0 to consider the value as a number. Example:
SELECT v
FROM
(SELECT 'SY1' v UNION SELECT 'SY16') t
WHERE SUBSTR(t.v, 3)+0 > 10
;
CREATE FUNCTION normalize_district (district VARCHAR(4))
RETURNS VARCHAR(4) DETERMINISTIC
RETURN CONCAT( TRIM(TRAILING CASE WHEN 0 + RIGHT(district, 2) > 0
THEN RIGHT(district, 2)
ELSE RIGHT(district, 1) END FROM district),
LPAD(CASE WHEN 0 + RIGHT(district, 2) > 0
THEN 0 + RIGHT(district, 2)
ELSE 0 + RIGHT(district, 1) END, 2, '0') );
and then
SELECT *
FROM district_to_test
LEFT JOIN rate ON normalize_district(district_to_test.district)
BETWEEN normalize_district(district_from)
AND normalize_district(district_to);
fiddle
0 + RIGHT(district, 2) > 0 in the function thecks does the last 2 symbols in district are digits.
If true then 2-digit number wil be extracted by RIGHT(), and the whole expression value will be above zero (you claim that there is no values like 'AA0' or 'AA00').
If false, and only one digit is present, then RIGHT() will give a substring which is started from a letter, and the value will be zero.
Based on this I divide the whole value to a prefix and numeric postfix, and add a zero to the numeric part making it 2-digit unconditionally. Such value can be used for direct string comparing by BETWEEN operator.
The goal of a function is to convert the value to 'AA00' format. For this purposes we must divide the whole value to textual and numeric parts and normalize (zero-pad) the latter one.
You may use any other dividing method. For example, you may check does the value contains two digits using LIKE '%\\d\\d'. Or backward, you may determine does the value contains two letters using LIKE '\\D\\D%'... these methods have relatively equal difficulty.

Natural Sorting SQL ORDER BY

Can anyone lend me a hand as to what I should append to my ORDER BY statement to sort these values naturally:
1
10
2
22
20405-109
20405-101
20404-100
X
Z
D
Ideally I'd like something along the lines of:
1
2
10
22
20404-100
20405-101
20405-109
D
X
Z
I'm currently using:
ORDER BY t.property, l.unit_number
where the values are l.unit_number
I've tried doing l.unit_number * 1 and l.unit_number + 0 but they haven't worked.
Should I be doing sort of ORDER conditional, such as Case When IsNumeric(l.unit_number)?
Thank you.
This will do it:
SELECT value
FROM Table1
ORDER BY value REGEXP '^[A-Za-z]+$'
,CAST(value as SIGNED INTEGER)
,CAST(REPLACE(value,'-','')AS SIGNED INTEGER)
,value
The 4 levels of the ORDER BY:
REGEXP assigns any alpha line a 1 and non-alphas a 0
SIGNED INT Sorts all of the numbers by the portion preceding the dash.
SIGNED INT after removing the dash sorts any of the items with the same value before the dash by the portion after the dash. Potentially could replace number 2, but wouldn't want to treat 90-1 the same as 9-01 should the case arise.
Sorts the letters alphabetically.
Demo: SQL Fiddle

MySQL String Comparison with Percent Output (Position Very Important

I am trying to compare two entries of 6 numbers, each number which can either can be zero or 1 (i.e 100001 or 011101). If 3 out of 6 match, I want the output to be .5. If 2 out of 6 match, i want the output to be .33 etc.
Note that position matters. A match only occurs when both entries have a 1 in the first position, both have a 0 in the second position etc.
Here are the SQL commands to create the table
CREATE TABLE sim
(sim_key int,
string int);
INSERT INTO sim (sim_key, string)
VALUES (1, 111000);
INSERT INTO sim (sim_key, string)
VALUES (2, 101101);
My desired output to compare the two strings, which share 50% of the characters, and output 50%.
Is it possible to do this sort of comparison in SQL? Thanks in advance
Have a look at this example.
CREATE TABLE sim (sim_key int, string int);
INSERT INTO sim (sim_key, string) VALUES (1, 111000);
INSERT INTO sim (sim_key, string) VALUES (2, 101101);
select a.string A, b.string B,
sum(case when Substring(A.string,Pos,1) = Substring(B.string,Pos,1) then 1 else 0 end) Matches,
count(*) as RowCount,
(sum(case when Substring(A.string,Pos,1) = Substring(B.string,Pos,1) then 1 else 0 end) /
count(*) * 100.0) as PercentMatch
from sim A
cross join sim B
inner join (
select 1 Pos union all select 2 union all select 3
union all select 4 union all select 5 union all select 6) P
on P.Pos between 1 and length(A.string)
where A.sim_key= 1 and B.sim_key = 2
group by a.string, b.string
It is crude and probably included more than required but shows how it can be done. It is better to create a numbers table with just numbers from 1 to 1000 or so, that can be used repeatedly in many queries where a number sequence is required. Such a table will replace the (select .. union virtual table used in the inner join)
Instead of keeping 10010101 as integer convert this binary version to true integer when compare use bit logic AND, result convert to binary and count '1' to how many match...
for convert: http://dev.mysql.com/doc/refman/5.5/en/binary-varbinary.html
for compare: http://dev.mysql.com/doc/refman/5.5/en/bit-functions.html bitwise AND
...