Find next greater number with zeros in sql number - sql

I'm looking for a way to find next greater number starting by 1 and followed by zeros in Microsoft SQL. Numbers could vary in digits. ie:
Query: 9856, Result after procedure: 10000
Query: 98999, Result after procedure: 100000
Thanks.
EDIT: There is no chance of having negative numbers. This is a calculation for a energy meter. For example, numbers can go up to 99999 or 999999 or 9999999. When energy overcome that number, it will start again at 0. So I can't read what energy has been used in that period. To know it, I need to calculate the number as asked, then perform some basic maths.
There is no need for knowing what is going on on 10, 100, etc, because of the nature of the operation. It will only be used when the above escenario happend.

I don't know why you require or mathematically any other formula can be implemented. but technically that can be achieved as follows
DECLARE #count INT
SET #count = 1000
DECLARE #result INT
SET #result = CASE WHEN #count%10 = 0 THEN #count ELSE CAST('1'+REPLICATE('0',LEN(#count)) AS INT) end
SELECT #result

This works for positive numbers (numbers greater than zero):
select power(10, ceiling( log10(the_number) )) from mytable;
In case the number is already a power of ten (1, 10, 100, ...) , the number itself is returned.

You can do this with just arithmetic operations:
select power(10, floor(log(v.n - 0.1, 10)) + 1)
from (values (1), (10), (8), (9982), (124)) v(n)

This is a fairly crude way of doing it, however it does work. The query basically looks at the number of digits your number has, assumes the next integer you want starts with a 1 and then adds the relevant number of 0's to it.
Note this only looks for the next increment and does not round down.
Also for 10 you will get 100 and for 1000 you will get 10000.
declare #number int = 98999;
declare #len int = len(#number);
declare #stringtoreturn nvarchar(200)='1';
declare #runs int = 1;
while #runs<=#len
begin
select #stringtoreturn = #stringtoreturn + '0';
select #runs=#runs+1;
end
select #stringtoreturn;

Related

How to do SQL Server rounding digit by digit?

A consultant has described a type of rounding I need to use in a financial application.
The following value: 0.01488
needs to be rounded in steps like this. We round each digit at a time,
0.0148 -> 0.015
0.015 -> 0.02
Thus the result is 0.02 (2 cents).
But if we did normal rounding to 2 dp the value 0.0148 would round to 0.01.
What is the name of this rounding? And how can I do it with SQL Server?
Update:
My example above is an arbitrary example. The starting value might be 0.15436798, i.e. any number of decimal places. It is related to the result of a previous multiplication. In that case I would need to round more times.
You can create a scalar function to do this job.
like:
CREATE function [dbo].[fn_roundx]( #num FLOAT,#round INT)
RETURNS FLOAT
AS
BEGIN
DECLARE #count INT=10;
WHILE #count > = #round
BEGIN
SET #num = ROUND(#num,#count);
SET #count=#count-1;
END;
RETURN #num
END
And then use it as per your conveneince for any depth of rounding you want?
For example
DECLARE #num FLOAT=0.014887;
SELECT #num AS ActualNumber,dbo.fn_roundx(#num,2) AS RoundedNumber
or
DECLARE #num FLOAT=0.014887;
SELECT #num AS ActualNumber,dbo.fn_roundx(#num,3) AS RoundedNumber
Sounds good?
How about something like following?
DECLARE #num decimal(20,5)=0.014880;
DECLARE #count INT=5;
DECLARE #round INT=2;
SELECT #num value;
WHILE #count > = #round
BEGIN
SET #num = ROUND(#num,#count);
SET #count=#count-1;
END;
SELECT #num value;
with following output..
for any number up to any number of round you want?
Use ROUND function twice
First time pass length as 3 to round 0.01488 to 0.01500
SELECT Round(0.01488, 3) -- 0.01500
On top of it pass length as 2 to round 0.01500 to 0.02000
SELECT Round(0.01500, 2) -- 0.02000
finally it should be something like this
DECLARE #num NUMERIC(16, 5) = 0.01488
SELECT Round(Round(#num, 3), 2)
Try this,
select round(round(0.01500,3),2)
select round(round(0.01488,3),2)

SQL: how to get the left 3 numbers from an int

I want to retrieve the left 3 numbers from an integer to be stored in a table. For example, if the int is 1234567, I want to retrieve 123. I want the second number (123) to also be an int; I don't want to convert anything to a string.
(And yes, really I should be working with strings. But I don't have control over that aspect of the issue.)
Thank you!
For SQL Server, the easiest way would definitely be:
SELECT CAST(LEFT(CAST(YourInt AS VARCHAR(100)), 3) AS INT)
Convert to string, take the left most three characters, and convert those back to an INT.
Doing it purely on the numerical value gets messy since you need to know how many digits you need to get rid of and so forth...
If you want to use purely only INT's, you'd have to construct something like this (at least you could do this in SQL Server - I'm not familiar enough with Access to know if that'll work in the Access SQL "dialect"):
DECLARE #MyInt INT = 1234567
SELECT
CASE
WHEN #MyInt < 1000 THEN #MyInt
WHEN #MyInt > 10000000 THEN #MyInt / 100000
WHEN #MyInt > 1000000 THEN #MyInt / 10000
WHEN #MyInt > 100000 THEN #MyInt / 1000
WHEN #MyInt > 10000 THEN #MyInt / 100
WHEN #MyInt > 1000 THEN #MyInt / 10
END AS 'NewInt'
But that's always an approximation - what if you have a really really really large number..... it might just fall through the cracks....
Without casting to string, how about this?
(T-SQL)
select #i / power(10,floor(log10(#i))-2)
Throws an error if the int is less than 100, but seems to work otherwise.
EDIT: To handle the error gracefully, you'd have to use a CASE since TSQL has no GREATEST() function...
select #i / case when #i < 100 then 1 else power(10,floor(log10(#i))-2) end
In access SELECT clng(left(cstr(field), 3)) FROM T should work.
Edit: Infact I bet it wont care about the cstr().
;WITH c10 AS
(
SELECT
Number
FROM
MyTable --?? WHERE Number>=1000
UNION ALL
SELECT Number/10 FROM c10 WHERE Number>=1000
)
SELECT Number FROM c10 WHERE Number < 1000
I can't test this, but it should do the trick. Iterate through until you end up with < 1000, relying on integer division. You may need to filter on the first clause to fine tune it
For a raw TSQL SQL Server 2005 solution only
well if you have access to php you could use substr
echo substr('1234567', 0, 3); and then convert the string back to an int
Converting an integer to a string in PHP
good luck!

Splitting decimal in sql

I am getting result as decimal in stored procedure. If I am getting result as 123.45,
I want to split it into 123 and 45. Can anybody help?
use SQL function FLOOR() for getting integer part
and subtract that from the original for the decimal part
You can also make use of ROUND instead of FLOOR.
See section C. Using ROUND to truncate for trucate, and then subtract that from the original.
Be aware that using FLOOR on negative numbers might not give you the required result.
Have a look at this example
DECLARE #Dec DECIMAL(12,8)
SET #Dec = -123.45
SELECT FLOOR(#DEc)
select round(#Dec, 0, 1)
try this;
DECLARE #result DECIMAL(8,2) = 123.45
SELECT CAST(round(#result,0) AS FLOAT)
SELECT REPLACE(#result % 1 ,'0.','')
OR
DECLARE #result decimal(8,2) = 123.45
select PARSENAME(#result, 2) AS LeftSideValue, PARSENAME(#result, 1) AS RightSideValue

Convert number to varchar in SQL with formatting

Is there a way in T-SQL to convert a TINYINT to VARCHAR with custom number formatting?
For instance, my TINYINT has a value of 3 and I want to convert it to a VARCH of 03, so that it always shows a 2 digit number.
I don't see this ability in the CONVERT function.
RIGHT('00' + CONVERT(VARCHAR, MyNumber), 2)
Be warned that this will cripple numbers > 99. You might want to factor in that possibility.
Use the RIGHT function...
e.g.
DECLARE #testnum TINYINT
SET #testnum = 3
PRINT RIGHT('00' + CONVERT(VARCHAR(2), #testnum), 2)
You can try this
DECLARE #Table TABLE(
Val INT
)
INSERT INTO #Table SELECT 3
INSERT INTO #Table SELECT 30
DECLARE #NumberPrefix INT
SET #NumberPrefix = 2
SELECT REPLICATE('0', #NumberPrefix - LEN(Val)) + CAST(Val AS VARCHAR(10))
FROM #Table
What is the value range? Is it 0 through 10? If so, then try:
SELECT REPLICATE('0',2-LEN(#t)) + CAST(#t AS VARCHAR)
That handles 0 through 9 as well as 10 through 99.
Now, tinyint can go up to the value of 255. If you want to handle > 99 through 255, then try this solution:
declare #t TINYINT
set #t =233
SELECT ISNULL(REPLICATE('0',2-LEN(#t)),'') + CAST(#t AS VARCHAR)
To understand the solution, the expression to the left of the + calculates the number of zeros to prefix to the string.
In case of the value 3, the length is 1. 2 - 1 is 1. REPLICATE Adds one zero.
In case of the value 10, the length is 2. 2 - 2 is 0. REPLICATE Adds nothing.
In the case of the value 100, the length is -1 which produces a NULL. However, the null value is handled and set to an empty string.
Now if you decide that because tinyint can contain up to 255 and you want your formatting as three characters, just change the 2-LEN to 3-LEN in the left expression and you're set.
declare #t tinyint
set #t =3
select right(replicate('0', 2) + cast(#t as varchar),2)
Ditto: on the cripping effect for numbers > 99
If you want to cater for 1-255 then you could use
select right(replicate('0', 2) + cast(#t as varchar),3)
But this would give you 001, 010, 100 etc
Here's an alternative following the last answer
declare #t tinyint,#v tinyint
set #t=23
set #v=232
Select replace(str(#t,4),' ','0'),replace(str(#t,5),' ','0')
This will work on any number and by varying the length of the str() function you can stipulate how many leading zeros you require. Provided of course that your string length is always >= maximum number of digits your number type can hold.
CorreciĆ³n: 3-LEN
declare #t TINYINT
set #t =233
SELECT ISNULL(REPLICATE('0',3-LEN(#t)),'') + CAST(#t AS VARCHAR)
Had the same problem with a zipcode field. Some folks sent me an excel file with zips, but they were formatted as #'s. Had to convert them to strings as well as prepend leading 0's to them if they were < 5 len ...
declare #int tinyint
set #int = 25
declare #len tinyint
set #len = 3
select right(replicate('0', #len) + cast(#int as varchar(255)), #len)
You just alter the #len to get what you want. As formatted, you'll get...
001
002
...
010
011
...
255
Ideally you'd "varchar(#len)", too, but that blows up the SQL compile. Have to toss an actual # into it instead of a var.

Round to n Significant Figures in SQL

I would like to be able to round a number to n significant figures in SQL. So:
123.456 rounded to 2sf would give 120
0.00123 rounded to 2sf would give 0.0012
I am aware of the ROUND() function, which rounds to n decimal places rather than significant figures.
select round(#number,#sf-1- floor(log10(abs(#number)))) should do the trick !
Successfully tested on your two examples.
Edit : Calling this function on #number=0 won't work. You should add a test for this before using this code.
create function sfround(#number float, #sf int) returns float as
begin
declare #r float
select #r = case when #number = 0 then 0 else round(#number ,#sf -1-floor(log10(abs(#number )))) end
return (#r)
end
Adapted the most popular answer by Brann to MySQL for those who come looking like me.
CREATE FUNCTION `sfround`(num FLOAT, sf INT) # creates the function
RETURNS float # defines output type
DETERMINISTIC # given input, will return same output
BEGIN
DECLARE r FLOAT; # make a variable called r, defined as a float
IF( num IS NULL OR num = 0) THEN # ensure the number exists, and isn't 0
SET r = num; # if it is; leave alone
ELSE
SET r = ROUND(num, sf - 1 - FLOOR(LOG10(ABS(num))));
/* see below*/
END IF;
RETURN (r);
END
/* Felt too long to put in comment */
ROUND(num, sf - 1 - FLOOR(LOG10(ABS(num))))
The part that does the work - uses ROUND function on the number as normal, but the length to be rounded to is calculated
ABS ensures positive
LOG10 gets the number of digits greater than 0 in the number
FLOOR gets the largest integer smaller than the resultant number
So always rounds down and gives an integer
sf - 1 - FLOOR(...) gives a negative number
works because ROUND(num, -ve num) rounds to the left of the decimal point
For just a one off, ROUND(123.456, -1) and ROUND(0.00123,4)
return the requested answers ((120, 0.0012)
I think I've managed it.
CREATE FUNCTION RoundSigFig(#Number float, #Figures int)
RETURNS float
AS
BEGIN
DECLARE #Answer float;
SET #Answer = (
SELECT
CASE WHEN intPower IS NULL THEN 0
ELSE FLOOR(fltNumber * POWER(CAST(10 AS float), intPower) + 0.5)
* POWER(CAST(10 AS float), -intPower)
END AS ans
FROM (
SELECT
#Number AS fltNumber,
CASE WHEN #Number > 0
THEN -((CEILING(LOG10(#Number)) - #Figures))
WHEN #Number < 0
THEN -((FLOOR(LOG10(#Number)) - #Figures))
ELSE NULL END AS intPower
) t
);
RETURN #Answer;
END
You could divide by 100 before rounding and then multiplying by 100...