2011-05-06 60 views
8

我需要從累計值中計算一個百分比。要應用於每行中每個值的百分比率取決於從另一個表中獲取的費率。百分比費率計算需要以分層的方式進行,因爲稅收可能按收入計算。如何根據另一個表中的組編寫一條sql語句來計算總計?

例如: 工資= 1000
600 * 10%[以較低的稅率首先$ 600計算]
400 * 30%

所以[在較高稅率的剩餘量計算出],我已經試圖讓這個工作,但不能整理出來。 DBA離開了,所以它已經交給我了。大多數SQL我可以,但我不知道如何處理這個問題,或者我應該在谷歌搜索,所以道歉是這是一個簡單的搜索,請直接指向我的網址,我會自己動手做!

無論如何,下面是數據表(#v)的格式示例和範圍表(#tiers)的示例,以及我到目前爲止的情況。我需要一個新的列,其中正確的百分比率級別的'cval'的計算正如我上面所解釋的。

希望有人能幫助或指引我正確的方向! 謝謝,J.

create table #v(
id nvarchar(50), 
val money, 
tid int 
) 

insert into #v values ('a',30,1) 
insert into #v values ('b',50,1) 
insert into #v values ('c',10,1) 
insert into #v values ('d',30,1) 
insert into #v values ('e',-80,1) 


create table #tiers (
tid int, 
threshold money, 
amount money 
) 

insert into #tiers values (1,0,30) 
insert into #tiers values (1,40,40) 
insert into #tiers values (1,100,50) 


select * from 
(
select v1.id, v1.tid, v1.val,sum(v2.val) cval 
from #v v1 
inner join #v v2 on v1.id >= v2.id 
group by v1.id, v1.val, v1.tid 
) a 
left join 
(
     select a.tid, a.id, a.threshold [lower], b.threshold [upper] from 
     (
       select rank() over (order by threshold) as id, tid, threshold, amount from #tiers 
     ) a 
     left join 
     (
       select rank() over (order by threshold) as id, tid, threshold, amount from #tiers 
     ) b on a.id = b.id-1 
) b on (a.cval >= lower and a.cval < upper) or (a.cval >= lower and upper is null) 

回答

2

假設在層級表中的金額列應該是一個稅率,你可以這樣做:你的回答

With VData As 
    (
    Select V1.id, V1.val, V1.tid, Sum(V2.val) As CVal 
    From #V As V1 
     Join #V As V2 
      On V2.id <= V1.id 
    Group By V1.id, V1.val, V1.tid 
    ) 
    , Tiers As 
    (
    Select T1.tid 
     , T1.Amount 
     , T1.threshold As MinThreshold 
     , Min(Coalesce(T2.threshold, 2147483647)) As MaxThreshold 
    From #tiers As T1 
     Left Join #tiers As T2 
      On T2.threshold > T1.threshold 
    Group By T1.tid, T1.Amount, T1.threshold 
    ) 
Select V.id, V.val, V.tid, V.CVal 
    , Sum(
     Case 
     When CVal > T.MaxThreshold Then T.Amount/100.00 * T.MaxThreshold 
     When CVal >= T.MinThreshold Then T.Amount/100.00 * (V.CVal - T.MinThreshold) 
     End) As TotalTax 
From VData As V 
    Join Tiers As T 
     On T.tid = V.tid 
Group By V.id, V.val, V.tid, V.CVal 
+0

標記爲正確,因爲我用它來編輯我的原始帖子,給我我想要的解決方案。 – Jason 2011-05-14 14:01:29

6

如果你的實際邏輯有很多規則,而不是這一個,你最好在像PL/SQL或T-SQL過程語言編寫,是因爲機會是..其他應用程序可能想要使用此邏輯使用..say .. * get_tax_for_pay(i_pay)*或類似的東西。

但是,如果這是你需要的,那麼下面的SQL應該足夠好。

在Oracle中進行了測試,因爲此刻我無法訪問SQL服務器。如果您在評論中發佈任何問題。最後的註釋。

create table gross_pay(
    pay number); 

insert into gross_pay values (1523); 
insert into gross_pay values (500); 
insert into gross_pay values (5600); 
insert into gross_pay values (3523); 
commit; 

create table tax_range(
    min_pay number, 
    max_pay number, 
    tax_percent number); 

insert into tax_range values (1000, 2000, 10); 
insert into tax_range values (2000, 3000, 20); 
insert into tax_range values (3000, 4000, 30); 
insert into tax_range values (4000, 100000, 35); 
commit; 

SQL> select * from gross_pay; 

     PAY 
---------- 
     1523 
     500 
     5600 
     3523 

SQL> select * from tax_range; 

    MIN_PAY MAX_PAY TAX_PERCENT 
---------- ---------- ----------- 
     1000  2000   10 
     2000  3000   20 
     3000  4000   30 
     4000  100000   35 

select g.pay, t.min_pay, t.max_pay, t.tax_percent, 
    (g.pay-t.min_pay) diff, (t.max_pay-t.min_pay) diff2, 
    (case when g.pay > t.min_pay then 
     least((t.max_pay-t.min_pay),(g.pay-t.min_pay)) 
     else 0 
    end) Taxable 
    from gross_pay g, tax_range t 
    order by pay, min_pay 
SQL>/

     PAY MIN_PAY MAX_PAY TAX_PERCENT  DIFF  DIFF2 TAXABLE 
---------- ---------- ---------- ----------- ---------- ---------- ---------- 
     500  1000  2000   10  -500  1000   0 
     500  2000  3000   20  -1500  1000   0 
     500  3000  4000   30  -2500  1000   0 
     500  4000  100000   35  -3500  96000   0 
     1523  1000  2000   10  523  1000  523 
     1523  2000  3000   20  -477  1000   0 
     1523  3000  4000   30  -1477  1000   0 
     1523  4000  100000   35  -2477  96000   0 
     3523  1000  2000   10  2523  1000  1000 
     3523  2000  3000   20  1523  1000  1000 
     3523  3000  4000   30  523  1000  523 

     PAY MIN_PAY MAX_PAY TAX_PERCENT  DIFF  DIFF2 TAXABLE 
---------- ---------- ---------- ----------- ---------- ---------- ---------- 
     3523  4000  100000   35  -477  96000   0 
     5600  1000  2000   10  4600  1000  1000 
     5600  2000  3000   20  3600  1000  1000 
     5600  3000  4000   30  2600  1000  1000 
     5600  4000  100000   35  1600  96000  1600 

select pay, sum(tax) from (
select pay, min_pay, max_pay, tax_percent, Taxable, 
     (Taxable* tax_percent/100) tax from (
select g.pay, t.min_pay, t.max_pay, t.tax_percent, 
     (g.pay-t.min_pay) diff, (t.max_pay-t.min_pay) diff2, 
     (case when g.pay > t.min_pay then 
       least((t.max_pay-t.min_pay),(g.pay-t.min_pay)) 
       else 0 
     end) Taxable 
    from gross_pay g, tax_range t 
    order by pay, min_pay 

     PAY SUM(TAX) 
---------- ---------- 
     1523  52.3 
     3523  456.9 
     500   0 
     5600  1160 

爲了計算...

  1. 你只是在一個特定支付左路下底傳中,該稅率給定閾值的數額徵稅的興趣。示例.. 1000 $不會因3k-5k稅收支架而被納稅。

  2. 在的情況下的量超過閾值,就會在該閾值 B)(付費閾值最小的最小的一個 )(最大 - 最小)) 所以充電。對於5500的工資,您只需在1000-2000美元的稅費中收取1000美元。 如果支付1200,則只需在1000-2000美元的稅費範圍內支付200美元。

  3. 如果您不在最小值和最大值的不同列中,您可以使用超前/滯後函數或自聯接來將它們放在與我的測試表相同的行中。如果您沒有最後一個範圍的最大值,請使用NVL或相應的函數來分配一個非常大的值來定義範圍。(或空:)代碼)

+0

謝謝,但我使用托馬斯的回答,因爲它更接近我原來的帖子。另外,由於MS Sql不支持您使用的某些語法,因此我無法測試您的測試結果。 – Jason 2011-05-14 14:02:36

+0

沒問題。我想我也學到了一些嘗試回答這個問題的東西......我只能訪問Oracle。我同意..托馬斯的帖子可能會對你有更多的幫助。祝你好運! – 2011-05-15 01:20:34

相關問題