如何根据另一个表中的组编写一个sql语句来计算总计?

Jas*_*son 8 sql t-sql sql-server

我需要从累积值计算一个百分比.要应用于每行中每个值的百分比率取决于从另一个表中获取的费率.百分比率计算需要以分层方式进行,因为税收可能会根据收入计算.

例如:工资= 1000
600*10%[首先按较低税率计算600美元]
400*30%[按较高税率计算的剩余金额]

所以,我一直试图让这个工作,但不能解决它.DBA离开了,所以它被移交给我.大多数SQL我都没问题,但我不知道如何处理这个问题,或者我应该在谷歌搜索的内容,所以道歉这是一个简单的搜索,请指导我到URL和我'我会尝试自己解决!

无论如何,下面是数据表(#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)
Run Code Online (Sandbox Code Playgroud)

Raj*_*thi 6

如果你的实际逻辑有比这个更多的规则,你最好用PL/SQL或T-SQL这样的过程语言编写它,因为很有可能..其他应用程序可能想要使用这个逻辑使用..say .. *get_tax_for_pay(i_pay)*或类似的东西.

但如果这就是你所需要的,那么下面的SQL应该足够好了.

在Oracle中测试过,因为我目前无权访问SQL Server.如果您有任何问题,请在评论中发布.最后的笔记.

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
Run Code Online (Sandbox Code Playgroud)

为了计算......

  1. 您只对特定工资超过税率范围的给定阈值的金额征税感兴趣.示例.. 1000美元不会在3k-5k税率范围内纳税.

  2. 如果金额超过阈值,您将在该阈值b)(最低支付阈值)中收取a)(最大 - 最小)的最小值.如果支付5500,您只需在1000-2000美元的税率范围内收取1000美元.如果是1200,你只需在1000-2000美元的税率范围内收取200美元.

  3. 如果您在不同的列中没有最小值和最大值,则可以使用超前/滞后函数或自联接将两者都放在与测试表中相同的行中.如果最后一个范围没有最大值,请使用NVL或相应的函数指定一个非常大的值来定义范围.(或空代码:))


Tho*_*mas 2

假设 Tiers 表中的 Amount 列应该是税率,您可以执行以下操作:

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
Run Code Online (Sandbox Code Playgroud)