Essentially, using SQL Server, I want to take the "Gross Amt" from the current table below (which is derived from a computed column upon INSERT
or UPDATE
) and then have that "Gross Amt" run through the "Tiered Table" to derive the "Total A $" in the desired output table.
I figured this would likely need to be done with a trigger (maybe a function?) since this calculation would happen upon INSERT
or UPDATE
and because the conditional logic could be incorporated into it since there are different tier tables with different Min/Max values and percentage thresholds for different tiers.
The example below is, of course, cumulative, and functions like marginal income tax rates, the first 10000 is at 90% (for Total A), the second tier calculates the 19999 at 60%, the third 69999 at 40%, and so on, etc. There are other regions with different tiers that are just simple lookup reference values.
Tiered table:
RegionID | TierNo | Min | Max | Total A | Total B |
---|---|---|---|---|---|
3 | 1 | 0 | 10000 | .90 | .10 |
3 | 2 | 10001 | 30000 | .60 | .40 |
3 | 3 | 30001 | 100000 | .40 | .60 |
3 | 4 | 100001 | 500000 | .40 | .60 |
3 | 5 | 500001 | 999999999999 | .20 | .80 |
Current table sample:
TransID | RegionID | GrossAmt | Total A % | Total A $ | Net Amt |
---|---|---|---|---|---|
100001 | 3 | 125000 |
Desired output:
TransID | RegionID | GrossAmt | Total A % | Total A $ | Net Amt |
---|---|---|---|---|---|
100001 | 3 | 125000 | 0.47 | 59000 | 66000 |
Any ideas or guidance would be extremely helpful and appreciated.
CodePudding user response:
Firstly, your tiers aren't quite right. For example, the first one begins at 0
and ends at 10000
, but the next one starts at 10001
, leaving anything between 10000
and 10001
unaccounted for. Instead, have your tiers abutting each other, and pick your intervals carefully using > AND <=
.
Secondly, this doesn't need a trigger at all. You should just calculate this on the fly when you need it. Create a view or an inline Table Valued Function if you need to.
It looks like a fairly simple grouped join, which you can do neatly using CROSS APPLY
. You just need to calculate how much to multiply for each tier: the lower of GrossAmt
or Max
, subtracting Min
SELECT
c.*,
[Total A %] = t.Total / c.GrossAmt,
[Total A $] = t.Total,
[Net Amt] = c.GrossAmt - t.Total
FROM CurrentData c
CROSS APPLY (
SELECT
Total = SUM((v.ActualMax - t.Min) * t.[Total A])
FROM Tiers t
CROSS APPLY (VALUES(
CASE WHEN c.GrossAmt < t.Max THEN c.GrossAmt ELSE t.Max END
)) v(ActualMax)
WHERE c.GrossAmt > t.Min
) t;
You can do this as an inline Table Valued Function if you want.
CREATE FUNCTION dbo.GetTieredTotal (@GrossAmt decimal(18,9))
RETURNS TABLE
AS RETURN
SELECT
Total = SUM((CASE WHEN @GrossAmt < t.Max THEN @GrossAmt ELSE t.Max END - t.Min) * t.[Total A])
FROM Tiers t
WHERE @GrossAmt > t.Min
;
You can then change the main query to
SELECT
c.*,
[Total A %] = t.Total / c.GrossAmt,
[Total A $] = t.Total,
[Net Amt] = c.GrossAmt - t.Total
FROM CurrentData c
CROSS APPLY dbo.GetTieredTotal (c.GrossAmt) t;