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

标签 sql sql-server tsql

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

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

所以,我一直在努力让它发挥作用,但无法解决。 DBA 不在,所以它已移交给我。大多数 SQL 我都可以,但我不确定如何解决这个问题,或者我应该在 google 中搜索什么,所以抱歉,这是一个简单的搜索,请直接将我定向到 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)

最佳答案

如果您的实际逻辑比这个规则有更多的规则,那么您最好用 PL/SQL 或 T-SQL 等过程语言编写它,因为很可能..其他应用程序可能希望使用此逻辑...说.. *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

用于计算...

  1. 您只对特定工资超过税级给定阈值的金额征税感兴趣。例如.. 3k-5k 税级中的 1000 美元不会被征税。

  2. 如果金额超过阈值,您将收取至少 a) (最大-最小) 在该阈值内 b)(最低工资阈值) 所以。对于 5500 美元的工资,您只需在 1000-2000 美元的税级中收取 1000 美元。 如果工资为 1200,您只需在 1000-2000 美元的税级中收取 200 美元。

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

关于sql - 如何编写 sql 语句来根据另一个表中的组计算总计?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5914451/

相关文章:

sql - 清理数据库

mysql - 查询存在最大(日期)的记录

sql - 如何在标签中生成带有非法字符的xml

sql - 为每个月递归选择两个字段

java - 将字符串放入preparedStatement中

sql-server - 具有 SQL Server 后端的 MS Access 应用程序的安全模型(部署)

sql-server - 窗口函数在子查询/CTE 中的行为不同?

sql-server - 如何创建损坏的 .bak 文件进行测试?

sql-server - 在 SQL Server 中,如何将数据插入到只有一列标识类型的表中?

sql - Varchar(Max) 在 Exec 中不起作用