Reputation: 11
I have a value from a table that I want to reduce for each percentage e.g.
Table 1
ID Percentage FKID
1 5 1
2 10 1
3 4 1
Table 2
ID AMOUNT
1 100
Declare @qty decimal
Select @qty = amount
From table2 where id = 1
Select @qty = @qty – @qty/100 * percentage
From Table1
I would expect 5% of 100, 10% of 95 then, 4% of 85.5. So my overall total would be 82.1 but I keep getting % of the amount, so 5% of 100, 10% off 100 and 4% off 100.
Is there a way of doing what I am trying to achieve?
Upvotes: 1
Views: 508
Reputation: 29667
If the goal is to merely calculate a variable for a given Table2.ID ?
Then that method you used can work for it.
But tables contain unordered sets.
So you need to include an ORDER BY
to respect the order that the percentages are subtracted.
Sample data:
CREATE TABLE Table2 ( ID INT IDENTITY(1,1) PRIMARY KEY, Amount INT ); INSERT INTO Table2 (Amount) VALUES (100),(100) ; CREATE TABLE Table1 ( ID INT IDENTITY(1,1) PRIMARY KEY, Percentage INT NOT NULL, FKID INT NOT NULL, FOREIGN KEY (FKID) REFERENCES Table2(ID) ); INSERT INTO Table1 (Percentage, FKID) VALUES (5,1), (10,1), (4,1), (30,2), (25,2), (20,2)
T-Sql:
DECLARE @Id INT = 1; DECLARE @qty FLOAT; SELECT @qty = Amount FROM Table2 WHERE ID = @Id; SELECT @qty = @qty-((@qty/100.0)*t1.Percentage) FROM Table1 t1 WHERE t1.FKID = @Id ORDER BY t1.ID; SELECT CAST(@qty AS DECIMAL(16,2)) AS qty
| qty | | :---- | | 82.08 |
A test on db<>fiddle here
Upvotes: 0
Reputation: 3288
You're looking for the result of this expression since it doesn't matter the order of the multiplication.
100 * (0.95 * 0.9 * 0.96)
You can emulate chaining the products using LOG
, SUM
, and EXP
to get the desired result
SELECT
val.ID, EXP(SUM(LOG(0.01*(100-Percentage)))) * MAX(Amount)
FROM
percents
INNER JOIN
val
ON percents.FKID = val.ID
GROUP BY
val.ID;
http://sqlfiddle.com/#!18/60c27/1
Upvotes: 1
Reputation: 95588
The only way (unfortunately) you can do this is iteratively; which means using an rCTE. Assuming that Percentage
can't be a negative value:
CREATE TABLE dbo.Table1 (ID int,
[Percentage] int, --Ideally you should store percentages as a decimal, that is what that are after all. E.g. 10% = 0.10.
FKID int);
CREATE TABLE dbo.Table2 (ID int,
Amount decimal(5, 1));
GO
INSERT INTO dbo.Table1 (ID,
[Percentage],
FKID)
VALUES (1, 5, 1),
(2, 10, 1),
(3, 4, 1);
GO
INSERT INTO dbo.Table2 (ID,
Amount)
VALUES (1, 100);
GO
SELECT T2.ID AS ID2,
T1.ID AS ID1,
CONVERT(decimal(6, 2), T2.Amount * ((100 - T1.[Percentage]) / 100.0)) AS Amount
FROM dbo.Table2 T2
JOIN dbo.Table1 T1 ON T2.ID = T1.ID
WHERE T1.ID = 1;
GO
WITH rCTE AS
(SELECT T2.ID AS ID2,
T1.ID AS ID1,
CONVERT(decimal(6, 2), T2.Amount * ((100 - T1.[Percentage]) / 100.0)) AS Amount
FROM dbo.Table2 T2
JOIN dbo.Table1 T1 ON T2.ID = T1.ID
WHERE T1.ID = 1
UNION ALL
SELECT r.ID2,
T1.ID,
CONVERT(decimal(6, 2), r.Amount * ((100 - T1.[Percentage]) / 100.0))
FROM rCTE r
JOIN dbo.Table1 T1 ON r.ID2 = T1.FKID
AND r.ID1 + 1 = T1.ID)
SELECT MIN(r.Amount)
FROM rCTE r
GROUP BY r.ID2;
GO
DROP TABLE dbo.Table1;
DROP TABLE dbo.Table2;
Upvotes: 1