Round *UP* to the nearest 100 in SQL Server - sql-server

Is it possible to easily round a figure up to the nearest 100 (or 1000, 500, 200 etc.) in SQL Server?
So:
720 -> 800
790 -> 800
1401 -> 1500

The following should work. After reading your question, I'm not exactly sure what you want 100 to return. For this 100 returns 100.
select floor((X + 99) / 100) * 100;
This gives the following results:
0 -> 0
1 -> 100
99 -> 100
100 -> 100
101 -> 200

For rounding Up to the nearest thousand, try the following:-
select round(YourValue, -3)

One option would be to use the CEILING() function like this:
SELECT CEILING(#value/100.0) * 100
You may need to convert your value to a decimal first depending on its type.

Use CEILING function to round a figure up
DECLARE #Number DECIMAL, #RoundUp DECIMAL
SET #RoundUp = 100
SET #Number = 720
SELECT CEILING(#Number/#RoundUp)*#RoundUp

Try this:
select round(#value , -2);

It is very simple to round a number to any multiple of nearest 10 by using simply the ROUND function
for ex:
SELECT ROUND(number/1000,2)*1000
This will give you the nearest thousandth value.

This will work for the values with decimal also.
select floor((ceiling (#value) + 99) / 100) * 100;

There's no native function that will do this, but there are any number of simple math tricks that will. An example:
DECLARE #Foo int
SET #Foo = 720
print #Foo
print (#Foo + 100) % 100
PRINT #Foo - (#Foo + 100) % 100

You can use this code, assuming your amount is an int. If not you will need to cast, so you get integer division.
If amount % 100 != 0 Then
roundedAmount = ((amount / 100) * 100) + 100
Else
roundedAmount = amount
You might want to package this into a user defined function.

A generic solution - Use MOD to find the last 100th place and then add 100 to the result.
select (720 - MOD(720,100)) + 100 from dual;
If you need the next 80th place, just replace any "100" with "80".

In addition to Gray's answer,
I'd use the following inline function:
CREATE FUNCTION dbo.udf_RoundNearest
(
#Number bigint,
#RoundNearest bigint,
#Direction int
)
RETURNS TABLE AS
RETURN
SELECT CASE WHEN #RoundNearest>=#Number THEN #Number
ELSE
(
(#Number + CASE
WHEN #Direction = 0 --Round Down
THEN 0
ELSE CASE WHEN #Number % #RoundNearest = 0 THEN 0 ELSE #RoundNearest END
END) / #RoundNearest) * #RoundNearest
END Number
Parameter Definition:
#Number - the number you need to round
#RoundNearest 10th, 100th , 1000th etc
#Direction 0-> round down, 1-> round up
using the function:
SELECT * FROM dbo.udf_RoundNearest (1965,100,1) --> 2000
SELECT * FROM dbo.udf_RoundNearest (1359,100,0) --> 1300
SELECT * FROM dbo.udf_RoundNearest (1999,10,0) --1990
SELECT * FROM dbo.udf_RoundNearest (80,100,0) --> 80 (if the #number parameter is less or equal the #RoundNearest parameter the result will be the #number itself
it can also be used as apply it versus a table
such as:
;with tmp (Value) as
(select 1236 union all select 6584 union all select 9999)
select t.*, fn.Number
from tmp t
cross apply dbo.udf_RoundNearest (Value,100,0) fn
/*Result Set
Value Number
1236 1200
6584 6500
9999 9900*/

This worked fine for me.
Round(#value/100, 0) * 100

It works fine for integer value:
#roundUpValue = ((#intValue / 1000) + 1) * 1000
#roundDownValue = (#intValue / 1000) * 1000
For example
declare #intValue as int = 1934
select ((#intValue / 1000) + 1) * 1000 as roundUp
select (#intValue / 1000) * 1000 as roundDown
If you want to round up to the nearest 500 then
select ((#intValue / 500) + 1) * 500 as roundUp

Select round(value/100,0)*100
Whatever number you want to round to, just post that instead of 100 here.

i have create a function in mssql it can help you
CREATE function dbo.roundup
(
#numbr decimal(18,2),
#frac decimal(18,2)
)
RETURNS decimal(18,2)
AS
BEGIN
DECLARE #result decimal(18,2)
set #result = ceiling(#numbr/#frac)*#frac
RETURN #result
END
GO

Related

How to convert HHMMSS to seconds using T-SQL

SQL server table msdb.dbo.sysjobhistory returns run_time and run_duration as INTEGER value formatted as HHMMSS.
How to convert it to seconds?
Example:
163135 (16:31:35) becomes 59495 (seconds)
Meanwhile I figured out this formula:
SELECT DATEDIFF(SECOND, '00:00:00', FORMAT(run_duration, '00:00:00'))
FROM msdb.dbo.sysjobhistory
You can use modulo and integer division to separate the hours, minutes, and seconds, multiply by number of seconds in each result, then sum.
DECLARE #hms int = 163135;
SELECT #hms / 10000 * 3600
+ #hms % 10000 / 100 * 60
+ #hms % 100;
59495
To use this as a view, it's really not any different:
CREATE VIEW dbo.viewname
AS
SELECT <other cols>, run_duration,
run_duration_s = run_duration / 10000 * 3600
+ run_duration % 10000 / 100 * 60
+ run_duration % 100
FROM msdb.dbo.sysjobhistory
WHERE ...
If you don't like math so much, you can treat it like a string:
DECLARE #hms int = 163135;
DECLARE #s char(6) = RIGHT(CONCAT('000000', #hms), 6);
SELECT LEFT(#s, 2) * 60 * 60
+ SUBSTRING(#s, 3, 2) * 60
+ RIGHT(#s, 2);
59495
However, this latter solution may need some tweaking if you could have durations > 99 hours, since now the string will be 7 digits. Maybe safer to use:
DECLARE #hms int = 163135;
DECLARE #s char(24) = RIGHT(CONCAT(REPLICATE('0',24), #hms), 24);
SELECT LEFT(#s, 20) * 60 * 60
+ SUBSTRING(#s, 21, 2) * 60
+ RIGHT(#s, 2);
24 is a ludicrous example, but safe. The job would have had to start in 1990 to hit 10 digits today.

Increasing a Column value by a % range

I have a table in SQL Server 2012. The following query works great:
SELECT TOP 300 [ObjectID], [tbh_Objects].Title, [Discount], [tbh_Section].Title
FROM [ECom].[dbo].[tbh_Objects]
INNER JOIN [tbh_Section] ON tbh_Objects.SectionID = tbh_Section.SectionID
ORDER BY tbh_Objects.AddedDate DESC
I want to fire a query which increases the discount value to a random % in the range of 5-10 for all 300 rows at once. So for eg: If DIscount of ObjectID=500 is 30, and the random value between 5 and 10 is "6", I want it to become 30+6%of30 for ObjectID=500.
Similarly for Object ID=230, let's say discount is 20 and the random value is 8, I want it as 20+8%of20.
The end result of the Discount should always be a whole number and not a decimal, so automatically rounds off.
Is this possible in SQL Server? How?
You need random integers and a Modulus (%) operator. A possible approach to generate a random integers is using a combination of NEWID() and CHECKSUM() functions. The following simplified example is a possible solution to your problem:
SELECT
Discount,
RandomPercent,
CONVERT(int, (Discount * (100.0 + RandomPercent) / 100)) AS NewDiscount
FROM (
SELECT Discount, (ABS(CHECKSUM(NEWID()) % 6) + 5) AS RandomPercent
FROM (VALUES (30), (20), (50), (70), (11), (21), (13), (15), (1), (6)) v (Discount)
) t
Result:
Discount RandomPercent NewDiscount
----------------------------------
30 7 32
20 5 21
50 6 53
70 10 77
11 9 11
21 9 22
13 8 14
15 10 16
1 6 1
6 5 6
If you need an UPDATE statement:
;WITH UpdateCTE AS (
SELECT TOP 300 o.[Discount]
FROM [ECom].[dbo].[tbh_Objects] o
INNER JOIN [tbh_Section] s ON o.SectionID = s.SectionID
ORDER BY o.AddedDate DESC
)
UPDATE UpdateCTE
SET [Discount] = CONVERT(int, (o.[Discount] * (100.0 + (ABS(CHECKSUM(NEWID()) % 6) + 5)) / 100))
If you want to round the new discounts before the integer conversion, use ROUND():
SET [Discount] = CONVERT(
int,
ROUND(o.[Discount] * (100.0 + (ABS(CHECKSUM(NEWID()) % 6) + 5)) / 100, 0)
)

Custom rounding in SQL

How can I set rules for custom rounding in SQL?
I need set this rules:
if second number after decimal is 1-2 eg. 10,02 - round it to 0 result 10,00
if second number after decimal is 3-7 eg. 10,13 - round it to 5 result 10,15
if second number after decimal is 8-9 eg. 10,28 - round it to bigger number result 10,3
Can someone help me how to do this? Round function works from 0-5 and above 5 but how to do "custom rounding function" based on this rules?
Thanks in advance.
One possible approach is the following statement:
SELECT
[Number],
CASE
WHEN ([Number] * 100) % 10 BETWEEN 3 AND 7 THEN ROUND([Number] + 0.02, 1) - 0.05
ELSE ROUND([Number] + 0.02, 1)
END [RoundedNumber]
FROM (VALUES (10.00), (10.01), (10.12), (10.13), (10.14), (10.28), (10.29)) v ([Number])
Result:
Number RoundedNumber
10.00 10.00
10.01 10.00
10.12 10.10
10.13 10.15
10.14 10.15
10.28 10.30
10.29 10.30
You can create your own function to use your custom rounding rules:
CREATE FUNCTION CustomRound(#num DECIMAL(18,2))
RETURNS DECIMAL(18,2)
AS
BEGIN
RETURN ROUND(#num, 1, 1) +
CASE WHEN (#num - ROUND(#num, 1, 1)) * 100 BETWEEN 1 AND 2 THEN 0
WHEN (#num - ROUND(#num, 1, 1)) * 100 BETWEEN 3 AND 7 THEN 0.05
WHEN (#num - ROUND(#num, 1, 1)) * 100 BETWEEN 8 AND 9 THEN 0.1
END
END
This function truncates the decimal number after first decimal place and add depending on the second decimal place a value to "round" as needed.
You can use the above function like this:
SELECT dbo.CustomRound(10.12) -- 10.10
SELECT dbo.CustomRound(10.02) -- 10.00
SELECT dbo.CustomRound(10.13) -- 10.15
SELECT dbo.CustomRound(10.28) -- 10.30
demo on dbfiddle.uk
You can also extend this function to be more dynamic using the custom rounding:
CREATE FUNCTION CustomRound(#num DECIMAL(18,6), #precision INT)
RETURNS DECIMAL(18,6)
AS
BEGIN
DECLARE #prec INT = IIF(#precision > 0, #precision - 1, 0);
RETURN ROUND(#num, #prec, 1) +
CASE WHEN (#num - ROUND(#num, #prec, 1)) * POWER(10, #precision) BETWEEN 1 AND 2 THEN 0.0 / POWER(10, #precision)
WHEN (#num - ROUND(#num, #prec, 1)) * POWER(10, #precision) BETWEEN 3 AND 7 THEN 5.0 / POWER(10, #precision)
WHEN (#num - ROUND(#num, #prec, 1)) * POWER(10, #precision) BETWEEN 8 AND 9 THEN 10.0 / POWER(10, #precision)
END
END
You can use this function like this:
SELECT dbo.CustomRound(10.12, 2) -- 10.10
SELECT dbo.CustomRound(10.02, 2) -- 10.00
SELECT dbo.CustomRound(10.13, 2) -- 10.15
SELECT dbo.CustomRound(10.28, 2) -- 10.30
-- or
SELECT dbo.CustomRound(10.102, 3) -- 10.100
SELECT dbo.CustomRound(10.002, 3) -- 10.000
SELECT dbo.CustomRound(10.103, 3) -- 10.105
SELECT dbo.CustomRound(10.208, 3) -- 10.210
demo on dbfiddle.uk
You can define your custome funtion and use it for ever
DECLARE #NUM REAL =10.01;
DECLARE #RESULT NVARCHAR(MAX)
IF #NUM=ROUND(#NUM,0)
BEGIN
SET #RESULT=#NUM
END
ELSE
BEGIN
DECLARE #NUM_STR VARCHAR(MAX)=CAST(#NUM AS VARCHAR(MAX)) -- CONVERT TO VARCHAR
DECLARE #LEFT VARCHAR(MAX)= CASE WHEN #NUM>=0 THEN FLOOR(#NUM) ELSE CEILING(#NUM) END -- GET LEFT SIDE NUMBERS
DECLARE #RIGHT VARCHAR(MAX)= REPLACE(#NUM_STR,CONCAT(#LEFT,'.'),'') -- GET RIGHT SIDE NUMBERS
... -- YOUR ROLES
END
You can multiply by 20, then round to the whole number and divide by 20 again.
e.g.
SELECT ROUND(myNum * 20,0) / 20.0
FROM myTable;

T-SQL / SQL Server : rounding after convert (decimal) SqlCommand

I want to normalize my SQL Server column before adding to datagridview, I did it in my SQL query. But I have a problem.
If the value fully dividing (for example 100/100=1) I don't want to see this value like 1.00000000000000. And if the value is not fully dividing (for example 3/7=0.42857142857), I want to round that value to two digits after rounding (0.43).
This is my code:
string q = "SELECT column1, column2, ((CONVERT(DECIMAL(18, 2), column3) / (SELECT MAX(column3) FROM tablename)) * 100) AS normalizedColumn3
FROM tablename .......;
I need to normalize column 3, it's values before normalize between 1 - 2000000. After normalize, values will be between 0.01 - 100.
Normalize formula:
column 3 = ((column 3 / maximum column 3) * 100)
Thank you for answers...
You'll have a small matter of data-loss if you only want two decimals. You'll need at least 5 decimals for values between 1 and 2,000,000
Example
Declare #YourTable table (Col3 float)
Insert into #YourTable values
(1),(1536),(1000000),(2000000)
Select A.*
,NewVal = convert(decimal(10,2), (Col3*100.0) / ( Select max(Col3) from #YourTable) )
From #YourTable A
Returns
Col3 NewVal
1 0.00 -- At decimal(10,5) you would see 0.00005
1536 0.08
1000000 50.00
2000000 100.00
I believe you can use ROUND ( numeric_expression , length [ ,function ] ) or SELECT ROUND(CAST (# AS decimal (#,#)),#); to round your decimal.
Here is more info on it :https://learn.microsoft.com/en-us/sql/t-sql/functions/round-transact-sql?view=sql-server-2017

TSQL query using calculation not returning value less than 1

I have a tsql query that does calculations for percentages, and it calculates fine if the result is > 1, but returns 0 when it is less than 1. My calculation is like so:
create table dbo.#temptable (
total_sold int null,
#_in_ny int null,
percent_in_ny decimal(18,2)null
) on [primary]
insert into dbo.#temptable
select count(t.booknum) as totalsold, t.#_in_ny, 100 * t.#_in_ny / count(t.booknum)
from mytable t
That gives me:
total ny sales %sales in ny
650 4 0 ---- this should show up as 0.61 since 4 is .61% of 650
The problem is that SQL Server does integer division. The simplest solution is to use 100.0 as the constant:
insert into dbo.#temptable
select count(t.booknum) as totalsold, t.#_in_ny,
t.#_in_ny * 100.0 / count(t.booknum)
from mytable t
t.#_in_ny / count(t.booknum) - You are doing integer division here. Convert both of these to floats or decimals.
insert into dbo.#temptable
select count(t.booknum) as totalsold, t.#_in_ny, 100 * CONVERT(float,t.#_in_ny) / CONVERT(float, count(t.booknum))
from mytable t
EDIT: See Gordon's answer as well. While either solution works, his is certainly a bit more eloquent than mine.

Resources