Is there a ROUNDDOWN() function in sql as there is in EXCEL - mysql

Say I have a table which has two columns i.e. Quantity and Percentages where my percentages are in decimals. Now I want to multiply these two columns and Round the value down to 2 decimals. Rounding down here means that all the numbers from 1-9 are rounded down. Is there an inbuilt function in SQL to do so as there is in Excel?
Examples:
13.567 should round to 13.56
136.7834 should round to 136.78
0.7699 should round to 0.76
I have tried searching for such a function online but couldn't come across an appropriate solution.

There's a FLOOR function, which can be adapted to your use case:
SELECT FLOOR(value * 100) / 100 AS RoundedValue

You can use TRUNCATE () for this rounddown
select TRUNCATE(2.847, 2) as rounddown
or
SELECT Floor(135.675); //for integer rounding, like 135
You can also use
select round(123.456, 2, 1) as rounddown
The 3rd parameter being non-zero will cause a truncation after the number of decimal points specified in the 2nd parameter.
DB Fiddle
https://www.ibm.com/support/knowledgecenter/en/SSEPEK_10.0.0/sqlref/src/tpc/db2z_bif_truncate.html
https://www.w3schools.com/sql/func_sqlserver_floor.asp

The solution to the problem is to truncate the extra decimal which can be achieved by using the extra parameter of the ROUND function which is ROUND(number, decimal_places, 0/1). Here if the last parameter is anything other than 0, it will truncate the rather than rounding off which is equivalent to the ROUNDDOWN() function of excel that I was looking for.
Alternatively, you can use the TRUNCATE() function, passing the number of decimal places to keep as the second parameter, which will drop off any extra decimals, acting as a ROUNDDOWN() function.

I hope this rounding utility helps somebody:
CREATE FUNCTION `get_round`(val DOUBLE, nDigits INT, RoundStyle VARCHAR(255)) RETURNS double
NO SQL
BEGIN
DECLARE a DOUBLE DEFAULT 0;
SET nDigits = ifnull(nDigits, 0);
CASE
WHEN UCASE(RoundStyle) IN ('ROUND NEAREST','', 'NEAREST', '', 'RND','ROUND', 'DEFAULT','DFLT', null) THEN #normal rounding, but up from 10.50#
SET a = round(val, nDigits);
WHEN UCASE(RoundStyle) IN('ROUND UP', 'UP') THEN #ROUND 10.554 to 10.56
SET a = ceil(val * (power(10, nDigits) )) / (power(10, nDigits));
WHEN UCASE(RoundStyle) IN('ROUND DOWN', 'DOWN') THEN #ROUND 10.555 to 10.55
SET a = truncate(val, nDigits) ;
WHEN UCASE(RoundStyle) IN('ROUND BANKER', 'BANKER','BANKERS ROUNDING') THEN #ROUND TO THE NEAREST EVEN 10.555 is 10.56 and 10.565 is 10.56
SET a = IF(ABS(val - TRUNCATE(val, nDigits)) * POWER(10, nDigits + 1) = 5
AND NOT CONVERT(TRUNCATE(ABS(val) * POWER(10, nDigits), 0), UNSIGNED) % 2 = 1,
TRUNCATE(val, nDigits), ROUND(val, nDigits));
WHEN UCASE(RoundStyle) IN('ROUND UP INTEGER', 'INT UP','UP INT') THEN #10.4 rounds to 11.0
SET a = ceiling(val);
WHEN UCASE(RoundStyle) IN('ROUND DOWN INTEGER', 'INT DOWN','DOWN INT') THEN #10.6 rounds to 10.0
SET a = floor(val);
END CASE;
RETURN ifnull(a, 0);
END

yes there are some Function in sql for round
ex:
SELECT ProductName, Price, FlOOR(Price) AS RoundedPrice
FROM Products;

Related

How to truncate double precision value in PostgreSQL by keeping exactly first two decimals?

I'm trying to truncate double precision value when I'm build json using json_build_object() function in PostgreSQL 11.8 but with no luck. To be more precise I'm trying to truncate 19.9899999999999984 number to ONLY two decimals but making sure it DOES NOT round it to 20.00 (which is what it does), but to keep it at 19.98.
BTW, what I've tried so far was to use:
1) TRUNC(found_book.price::numeric, 2) and I get value 20.00
2) ROUND(found_book.price::numeric, 2) and I get value 19.99 -> so far this is closesest value but not what I need
3) ROUND(found_book.price::double precision, 2) and I get
[42883] ERROR: function round(double precision, integer) does not exist
Also here is whole code I'm using:
create or replace function public.get_book_by_book_id8(b_id bigint) returns json as
$BODY$
declare
found_book book;
book_authors json;
book_categories json;
book_price double precision;
begin
-- Load book data:
select * into found_book
from book b2
where b2.book_id = b_id;
-- Get assigned authors
select case when count(x) = 0 then '[]' else json_agg(x) end into book_authors
from (select aut.*
from book b
inner join author_book as ab on b.book_id = ab.book_id
inner join author as aut on ab.author_id = aut.author_id
where b.book_id = b_id) x;
-- Get assigned categories
select case when count(y) = 0 then '[]' else json_agg(y) end into book_categories
from (select cat.*
from book b
inner join category_book as cb on b.book_id = cb.book_id
inner join category as cat on cb.category_id = cat.category_id
where b.book_id = b_id) y;
book_price = trunc(found_book.price, 2);
-- Build the JSON response:
return (select json_build_object(
'book_id', found_book.book_id,
'title', found_book.title,
'price', book_price,
'amount', found_book.amount,
'is_deleted', found_book.is_deleted,
'authors', book_authors,
'categories', book_categories
));
end
$BODY$
language 'plpgsql';
select get_book_by_book_id8(186);
How do I achieve to keep EXACTLY ONLY two FIRST decimal digits 19.98 (any suggestion/help is greatly appreciated)?
P.S. PostgreSQL version is 11.8
In PostgreSQL 11.8 or 12.3 I cannot reproduce:
# select trunc('19.9899999999999984'::numeric, 2);
trunc
-------
19.98
(1 row)
# select trunc(19.9899999999999984::numeric, 2);
trunc
-------
19.98
(1 row)
# select trunc(19.9899999999999984, 2);
trunc
-------
19.98
(1 row)
Actually I can reproduce with the right type and a special setting:
# set extra_float_digits=0;
SET
# select trunc(19.9899999999999984::double precision::text::numeric, 2);
trunc
-------
19.99
(1 row)
And a possible solution:
# show extra_float_digits;
extra_float_digits
--------------------
3
(1 row)
select trunc(19.9899999999999984::double precision::text::numeric, 2);
trunc
-------
19.98
(1 row)
But note that:
Note: The extra_float_digits setting controls the number of extra
significant digits included when a floating point value is converted
to text for output. With the default value of 0, the output is the
same on every platform supported by PostgreSQL. Increasing it will
produce output that more accurately represents the stored value, but
may be unportable.
As #pifor suggested I've managed to get it done by directly passing trunc(found_book.price::double precision::text::numeric, 2) as value in json_build_object like this:
json_build_object(
'book_id', found_book.book_id,
'title', found_book.title,
'price', trunc(found_book.price::double precision::text::numeric, 2),
'amount', found_book.amount,
'is_deleted', found_book.is_deleted,
'authors', book_authors,
'categories', book_categories
)
Using book_price = trunc(found_book.price::double precision::text::numeric, 2); and passing it as value for 'price' key didn't work.
Thank you for your help. :)

Mask integer field in mysql

I need to mask integer field in mysql such that 9999911111 becomes 9900001111. I want to keep first 2 digits and last 4 digits and need to mark rest of the digits as 0 for the integers stored in the field.
I have created a query and it's working but I am not sure whether this is right way to do for integers or not.
update table_name
set field_name=CONCAT(SUBSTR(field_name, 1, 2),
REPEAT('0', CHAR_LENGTH(field_name) - 6),
SUBSTR(field_name, CHAR_LENGTH(field_name)-3, CHAR_LENGTH(field_name)));
Just trying a different approach .
SET #myVar = 344553543534;
SELECT #myVar - (SUBSTRING(#myVar, 4, LENGTH(#myVar) - 7) * 10000) ;
Above mentioned formula will give 344000003534 as the result. Tried with different combination and found it working.
So your query need to change as given below
UPDATE table_name
SET field_name=
(field_name - (SUBSTRING(field_name, 4, LENGTH(field_name) - 7) * 10000));
Explanation :
Consider Number, a = 344553543534;
Expected Result, b = 344000003534;
c = (a - b) = 344553543534 - 344000003534 = 553540000;
Now if you consider the result, c, 55354 is the numbers where masking required, and 0000 indicates the last 4 number to be left open.
So to get masked value, we can use the formula, b = a - c;
So now to get c, used SUBSTRING(a, 4, LENGTH(a) - 7) * 10000
EDIT : To keep only first two numbers, use 3 instead of 4 and 6 instead of 7. I assumed that you needed to keep first 3.
SET #myVar = 344553543534;
SELECT #myVar - (SUBSTRING(#myVar, 3, LENGTH(#myVar) - 6) * 10000) ;

How do I use an excel function inside a custom function defined in VBA?

How do I use an excel function inside a custom function defined in VBA?
I want a custom round function that acts like MRound and RoundDown. To round to the nearest 25 millionths.
Public Function MRoundDown(Num As Double) As Double
Num = Num * 40000
Num = RoundDown(Num, 0)
Num = Num / 40000
End Function
I already figured it out myself, but it took entirely too long to find the help that I needed. So here's the solution.
The problem in trying to use RoundDown was that I had not specified the library to call that object from. Application is Excel, WorksheetFunction is where the RoundDown object is defined.
Public Function MRoundDown(Num As Double) As Double
Num = Num * 40000
Num = Application.WorksheetFunction.RoundDown(Num, 0)
Num = Num / 40000
MRoundDown = Num
End Function
I further improved the code like this:
Public Function MRD(Num As Double, Multiples As Double) As Double
Num = Num / Multiples
Num = Application.WorksheetFunction.RoundDown(Num, 0)
Num = Num * Multiples
MRD = Num
End Function
There's one more level of functionality that I could hope for, to be able to accept a percentage input and then be able to RoundDown only if the remainder is lower than x percent of the multiple. For instance given .25 as multiple, and .8 as the percentage, I would want it to round 1.19 to 1.00 and 1.20 to 1.25.

Mysql: Trim number to be between X and Y MIN/MAX

I don't know the terms or the exact word used for this, but I'm looking for a function inside MySQL that can trim a number to be between X and Y.
For example, something like this:
SELECT TRIM_NUMBER(NUMBER, MIN, MAX);
If I do: TRIM_NUMBER(50, 1, 100) it should be fine, and return 50.
But if I do something like: TRIM_NUMBER(999, 1, 100) it should return 100, because it's the MAX value I'v set it to. The same thing should apply for MIN.
Is there any such function included in MySQL ?
Try this
SELECT GREATEST(LEAST(NUMBER, 100), 1);
There isn't anything built in, but your code it yourself, like this:
select if(num < 1, 1, if (num > 100, 100, num))
If you want the "overkill" of a function, here's a suggestion:
create function trimNumber(x double, floorValue double, ceilValue double) returns double
begin
declare ans double;
if x >= floorValue and x <= ceilValue then
set ans = x;
else
if x < floorValue then
set ans = floorValue;
else
set ans = ceilValue;
end if;
end if;
return ans;
end
I think you are looking for something like that(from MySQL Reference Manual):
http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#operator_between
Just adding this because it is the ANSI standard way of expressing this:
select (case when num < 1 then 1
when num > 100 then 100
else num
end) as TrimmedNum

How to round down to nearest integer in MySQL?

How would I round down to the nearest integer in MySQL?
Example: 12345.7344 rounds to 12345
mysql's round() function rounds up.
I don't know how long the values nor the decimal places will be, could be 10 digits with 4 decimal places, could be 2 digits with 7 decimal places.
Use FLOOR:
SELECT FLOOR(your_field) FROM your_table
Use FLOOR().
It will to round your decimal to the lower integer. Examples:
SELECT FLOOR(1.9) /* return 1 */
SELECT FLOOR(1.1) /* return 1 */
Other useful rounding
If you want to round your decimal to the nearest integer, use ROUND(). Examples:
SELECT ROUND(1.9) /* return 2 */
SELECT ROUND(1.1) /* return 1 */
If you want to round your decimal to the upper integer, use CEILING(). Examples:
SELECT CEILING(1.9) /* return 2 */
SELECT CEILING(1.1) /* return 2 */
SELECT FLOOR(12345.7344);
Read more here.
SUBSTR will be better than FLOOR in some cases because FLOOR has a "bug" as follow:
SELECT 25 * 9.54 + 0.5 -> 239.00
SELECT FLOOR(25 * 9.54 + 0.5) -> 238 (oops!)
SELECT SUBSTR((25*9.54+0.5),1,LOCATE('.',(25*9.54+0.5)) - 1) -> 239
The FLOOR() function will return the largest integer value that is smaller than or equal to a number.
example :
SELECT FLOOR(columnName) FROM tableName;
It can be done in the following two ways:
select floor(desired_field_value) from table
select round(desired_field_value-0.5) from table
The 2nd-way explanation: Assume 12345.7344 integer. So, 12345.7344 - 0.5 = 12345.2344 and
rounding off the result will be 12345.
Try this,
SELECT SUBSTR(12345.7344,1,LOCATE('.', 12345.7344) - 1)
or
SELECT FLOOR(12345.7344)
SQLFiddle Demo
if you need decimals can use this
DECLARE #Num NUMERIC(18, 7) = 19.1471985
SELECT FLOOR(#Num * 10000) / 10000
Output: 19.147100
Clear: 985
Add: 00
OR use this:
SELECT SUBSTRING(CONVERT(VARCHAR, #Num), 1, CHARINDEX('.', #Num) + 4)
Output: 19.1471
Clear: 985
Both Query is used for round down the nearest integer in MySQL
SELECT FLOOR(445.6) ;
SELECT NULL(222.456);