Amount Calculation using Precision - sql

I have a salary table which has Amount and Amount Precision columns.
Using precision I want to get the actual amount.
Please help me to calculate actual amount using precision.

use POWER(). The multiplication with 1.0 is required to convert your Amount in integer into decimal
ActualAmount = Amount * 1.0 / Power(10, AmountPrecision)

You can use the following query:
select CAST(Amount as double precision) / power(10, AmountPrecision) from AmountTest
Assuming AmountTest is the name of the table. You can replace it with the name given by you.

DECLARE #T TABLE (
Amount INT,
AmountPrecision INT
)
INSERT INTO #T VALUES(1,1),(51,1),(51,2),(934,3),(1024,2)
SELECT
*,
CAST(AMOUNT AS FLOAT)/(CONCAT(1,REPLICATE(0,AMOUNTPRECISION))) AS ACTUALAMOUNT
FROM #T

You can also try the divide by just creating value using REPLICATE() function.
CREATE TABLE Data (id int, AmountPrecision int)
INSERT INTO Data (id, AmountPrecision) VALUES
(1, 1)
, (51, 1)
, (51, 2)
, (934, 3)
, (1024, 2)
Select id
, Cast('1' + REPLICATE('0', AmountPrecision) as int) as DivideBy
, Cast(id * 1.0 / Cast('1' + REPLICATE('0', AmountPrecision) as int)
as float) as FormattedNumber
from Data
Live db<>fiddle demo.

Related

Calculate average rate in SQL Server

declare #table as table
(
LedgerId int,
Transaction_Type varchar(50),
Inward_qty decimal (18,3),
Inward_rate decimal (18,3)
)
insert into #table
values (1, 'Issue', 67.320, 473.66),
(2, 'Receipt', 201.290, 657.90),
(3, 'Receipt', 94.860, 473.66)
select * from #table
I want to calculate the average rate the formula is finding the receipt and subtract from issue remaining will be multiplied by the rate we will have the value than total value divided by total receipt qty and we will get an inward rate I have no clue how to do this
Formula
201.290 - 67.320 = 133.970 (receipt - issue)
133.970 * 657.900 = 88,138.863(remaining receipt qty * rate) will get value
94.860 * 473.660 = 44,931.3876(receipt * rate) will get value
88,138.863 + 44,931.3876 = 1,33,070.2506 (sum of total value)
133.970 + 94.860 = 228.83(sum of total qty )
1,33,070.2506 / 228.83 (sum of total value) / (sum of total qty )
= 581.5244967880086 thus 581.524 is average rate
output layout as per above calculation
declare #table1 as table
(
LedgerId int,
Transaction_Type varchar(50),
Inward_qty decimal (18,3),
Inward_rate decimal (18,3)
)
insert into #table1 values(1,'Issue',67.320,473.66),(2,'Receipt',133.970,657.90),(3,'Receipt',94.860,473.66)
select * , inward_Value = Inward_qty * Inward_rate into #temp from #table1
declare #Qty decimal (18,3)
declare #value decimal (18,3)
set #Qty= (select sum(Inward_qty) from #temp where Transaction_Type ='Receipt' )
set #value =(select sum(inward_Value) from #temp where Transaction_Type ='Receipt' )
declare #Rate decimal (18,3) = #Value/#Qty
select #Rate
drop table #temp

Show data where the value is after the decimal point

I would like to do (select value from table where...) where the value of a given experiment is not an integer, but it is decimal
You can use FLOOR function to do this. It will round up your numbers, so you can pick only this that are not integers.
create table #t (i decimal(12,6))
insert into #t values (1), (1.1)
select * from #t where FLOOR(i) <> i
You can do as
CREATE TABLE T( Val DECIMAL(10, 2));
INSERT INTO T VALUES
(10.10), (10);
SELECT *
FROM T
WHERE CAST(Val AS INT) <> Val
Returns: 10.10

SQL rounding to decimal places

I have a dataset which i need to do a calculation on price and round to decimal places. But the results aren't quite what is expected. The calculation is in the case statement
CREATE TABLE #Temp ( ID INT IDENTITY(1,1), Price DECIMAL(7,2) )
INSERT INTO #TEMP ( Price )
VALUES ( 119.99 )
, ( 48.99 )
SELECT
ID
, Price
, CASE WHEN Price > 10 THEN CONVERT( DECIMAL(7,2), Price * 1.08 - 0.05 ) END AS RRP
FROM #Temp
DROP TABLE #Temp
with the results
ID Price RRP
1 119.99 129.54
2 48.99 52.86
I need to get the 129.54 to 129.55 and the 52.86 to 52.85 within the same case statement if that is possible to match up with another data set
Are you rounding to the nearest 5 cents because your country has gotten rid of the penny? This is the only logic that we can seem to follow with your expected results.
SELECT ID
,Price
,CASE
WHEN Price > 10
THEN ROUND(CONVERT(DECIMAL(7, 2), Price * 1.08 - 0.05) * 20, 0) / 20
END AS RRP
FROM #Temp
Assuming you want to round to the nearest 5 cents or nearst 5 in 100ths decimal position.
INSERT INTO #TEMP ( Price )
VALUES ( 119.99 )
, ( 48.99 )
SELECT
ID
, Price
, Price * 1.08 - 0.05
, CASE WHEN Price > 10 THEN CONVERT( DECIMAL(7,2), round((Price * 1.08 - 0.05)*20,0)/20) END AS RRP
FROM #Temp
DEMO:http://rextester.com/QIM12944

Transform view of table using sql

I have the following table
Date Input Output Rate
10/10/2001 10 15 0.5
10/11/2002 13 14 0.3
1. Date Input Output Rate
2. 10/10/2001 10 15 0.5
3. 10/11/2002 13 14 0.3
I need to transform this table in the following table:
1. Date Category Amount
2. 10/10/2001 Input 10
3. 10/10/2001 Output 15
4. 10/10/2001 Rate 0.5
5. 10/11/2002 Input 13
6. 10/11/2002 Output 14
7. 10/11/2002 Rate 0.3
Which query should I use?
Thank you in advance.
You can use UNPIVOT:
DECLARE #T TABLE (Date DATE, Input DECIMAL(5, 1), [Output] DECIMAL(5, 1), Rate DECIMAL(5, 1));
INSERT #T VALUES ('20011010', 10, 15, 0.5), ('20021110', 13, 14, 0.3);
SELECT upvt.Date, upvt.Category, upvt.Amount
FROM #T
UNPIVOT
( Amount
FOR Category IN ([input], [Output], [Rate])
) upvt;
However, I prefer the slightly more flexible CROSS APPLY with a table valued constructor:
DECLARE #T TABLE (Date DATE, Input DECIMAL(5, 1), [Output] DECIMAL(5, 1), Rate DECIMAL(5, 1));
INSERT #T VALUES ('20011010', 10, 15, 0.5), ('20021110', 13, 14, 0.3);
SELECT t.Date, upvt.Category, upvt.Amount
FROM #T AS t
CROSS APPLY
(VALUES
('Input', t.Input),
('Output', t.[Output]),
('Rate', t.Rate)
) AS upvt (Category, Amount);
As it affords you more flexibility with your datatype conversions, and with renaming your columns slightly differently, e.g. it is easier to make a column like CallStartTime something like Call Start, so it is more report friendly.
e.g if your input and output columns are actually integers, you will get an error message when using UNPIVOT:
The type of column "Rate" conflicts with the type of other columns specified in the UNPIVOT list.
So you would need to use a subquery, and convert your columns there:
DECLARE #T TABLE (Date DATE, Input INT, [Output] INT, Rate DECIMAL(5, 1));
INSERT #T VALUES ('20011010', 10, 15, 0.5), ('20021110', 13, 14, 0.3);
SELECT upvt.Date, upvt.Category, upvt.Amount
FROM ( SELECT Date,
Input = CONVERT(DECIMAL(5, 1), Input),
[Output] = CONVERT(DECIMAL(5, 1), [Output]),
Rate
FROM #T
) AS t
UNPIVOT
( Amount
FOR Category IN ([input], [Output], [Rate])
) upvt;
And while you have to do the same conversion with CROSS APPLY, it seems like less clutter to me:
DECLARE #T TABLE (Date DATE, Input INT, [Output] INT, Rate DECIMAL(5, 1));
INSERT #T VALUES ('20011010', 10, 15, 0.5), ('20021110', 13, 14, 0.3);
SELECT t.Date, upvt.Category, upvt.Amount
FROM #T AS t
CROSS APPLY
(VALUES
('Input', CONVERT(DECIMAL(5, 1), Input)),
('Output', CONVERT(DECIMAL(5, 1), [Output])),
('Rate', t.Rate)
) AS upvt (Category, Amount);
It is of course, personal preference.
You might use a simple Standard SQL UNION ALL which is supported by every DBMS -> portable :-)
SELECT Date, 'Input' AS Category, Cast(Input as DEC(5,1)) AS Amount
FROM Tab
UNION ALL
SELECT Date, 'Output' AS Category, Output
FROM Tab
UNION ALL
SELECT Date, 'Rate' AS Category, Rate
FROM Tab

SQL Server window function for running percentage

I know there are several examples of recursion with CTE and so on, but how can this be accomplished just by using window functions in SQL Server 2012:
CREATE TABLE #temp
(
ID INT PRIMARY KEY IDENTITY(1,1) NOT NULL,
Percentage INT NOT NULL
)
DECLARE #Calculated MONEY = 1000
INSERT INTO #temp ( Percentage ) VALUES ( 100 )
INSERT INTO #temp ( Percentage ) VALUES ( 90)
INSERT INTO #temp ( Percentage ) VALUES ( 60)
INSERT INTO #temp ( Percentage ) VALUES ( 50)
INSERT INTO #temp ( Percentage ) VALUES ( 100)
And the result would be a running percentage like so (we are starting with $1000)
id percentage calculated
-- -------- ---------
1 100 1000
2 50 500
3 90 450
4 80 360
5 100 360
So the value for the next row is the percentage multiplied by the calculated value above that row. Can LAG be used on a computed alias?
Thanks,
You need a running product of the percentages instead of always comparing 2 consecutive rows, which is why LEAD and LAG won't work here.
You can use a windowed sum to keep a running product of the percentages against your variable to get your desired calculation:
SELECT
ID,
Expected,
EXP(SUM(LOG(CONVERT(FLOAT, Percentage) / 100)) OVER (ORDER BY ID)) * #Calculated AS Actual
FROM #Temp
Adding this to your sample code (with a column I added for your expected output):
CREATE TABLE #temp
(
ID INT PRIMARY KEY IDENTITY(1,1) NOT NULL,
Percentage INT NOT NULL,
Expected MONEY NOT NULL
)
DECLARE #Calculated MONEY = 1000
INSERT INTO #temp ( Percentage, Expected ) VALUES ( 100 , 1000)
INSERT INTO #temp ( Percentage, Expected ) VALUES ( 50, 500)
INSERT INTO #temp ( Percentage, Expected ) VALUES ( 90, 450)
INSERT INTO #temp ( Percentage, Expected ) VALUES ( 80, 360)
INSERT INTO #temp ( Percentage, Expected ) VALUES ( 100, 360)
SELECT
ID,
Expected,
EXP(SUM(LOG(CONVERT(FLOAT, Percentage) / 100)) OVER (ORDER BY ID)) * #Calculated AS Actual
FROM #Temp
This will yield your expected output:
ID Expected Actual
----------- --------------------- ----------------------
1 1000.00 1000
2 500.00 500
3 450.00 450
4 360.00 360
5 360.00 360
you can use recursive cte to get the desired result
with cte
as
(
select id, percentage, 1000 as calculated
from #temp
where id =1
union all
select t.id, t.percentage, t.percentage*cte.calculated/100 as calculated
from #temp t
join cte
on t.id = cte.id+1
)
select * from cte
I'm afraid, widow functions won't help here (at least they won't make it simple). The easiest way to achieve your goal is update statement with double assignment:
alter table #temp add VAL decimal
declare #val decimal = 1000
update t set
#val = VAL = #val * Percentage / 100
from (select top 100 percent * from #temp order by id) as t
select * from #temp