用上限计算 SUM 并按比例乘以 SQL 中的系数
Calculate SUM with cap and multiply pro-rata by coefficient in SQL
我有 table 大致是这样的:
+--------+---------------------+--------+------+
| CustId | TransDate | Amount | Coef |
+--------+---------------------+--------+------+
| 1 | 2020-09-04 11:02:00 | 400 | 0.1 |
| 1 | 2020-09-04 12:05:00 | 500 | 0.2 |
| 1 | 2020-09-04 13:02:00 | 400 | 0.1 |
| 1 | 2020-09-04 13:11:00 | 600 | 0.4 |
| 2 | 2020-09-04 10:01:00 | 300 | 0.3 |
| 2 | 2020-09-04 11:02:00 | 700 | 0.2 |
+--------+---------------------+--------+------+
我想要实现的是给每个客户一个“奖金”,计算方式为金额 * 系数,但交易总额上限为 1,500。 “奖金”是针对 SUM <1,500 的客户交易授予的(按照交易进行的顺序)。
例如,客户“1”将在前 3 笔交易中获得全额赠金,在第 4 笔交易中获得 1,500 差价的赠金。基本上,最终结果应该是这样的:
+--------+---------------------+--------+------+---------------------------------------------------+
| CustId | TransDate | Amount | Coef | Bonus |
+--------+---------------------+--------+------+---------------------------------------------------+
| 1 | 2020-09-04 11:02:00 | 400 | 0.1 | 40 |
| 1 | 2020-09-04 12:05:00 | 500 | 0.2 | 100 |
| 1 | 2020-09-04 13:02:00 | 400 | 0.1 | 40 |
| 1 | 2020-09-04 13:11:00 | 600 | 0.4 | 80 /*(this is given only for the remaining 200)*/ |
| 2 | 2020-09-04 10:01:00 | 300 | 0.3 | 90 |
| 2 | 2020-09-04 11:02:00 | 700 | 0.2 | 140 |
+--------+---------------------+--------+------+---------------------------------------------------+
提前致谢!
干杯。
如果我没理解错的话,你想要一个累加和以及一些逻辑:
select t.*,
(case when sum(amount) over (partition by custid order by transdate) <= 1500
then coef * amount
when sum(amount) over (partition by custid order by transdate) - amount < 1500
then (1500 - sum(amount) over (partition by custid order by transdate)) as coef
else 0
end) as bonus
from t
[编辑]:现在使用 MAX 函数限制奖金金额。
数据
drop table if exists #tTEST;
go
select * INTO #tTEST from (values
(1, '2020-09-04 11:02:00', 400, 0.1),
(1, '2020-09-04 12:05:00', 500, 0.2),
(1, '2020-09-04 13:02:00', 400, 0.1),
(1, '2020-09-04 13:11:00', 600, 0.4),
(1, '2020-09-05 13:11:00', 600, 0.4),
(2, '2020-09-04 10:01:00', 300, 0.3),
(3, '2020-09-04 11:02:00', 700, 0.2)) V(CustId, TransDate, Amount, Coef);
查询
declare @bonus_limit int=1500;
with data_cte as (
select *, sum(amount) over (partition by custid order by transdate) cum_amount,
@bonus_limit-sum(amount) over (partition by custid order by transdate) cum_amount_diff
from #tTEST t)
select *,
(SELECT Max(v) FROM (VALUES (0), (case when cum_amount_diff<0 then (Amount+cum_amount_diff)*Coef
else Amount*Coef end)) AS value(v)) Bonus
from data_cte;
结果
+--------+---------------------+--------+------+------------+-----------------+-------+
| CustId | TransDate | Amount | Coef | cum_amount | cum_amount_diff | Bonus |
+--------+---------------------+--------+------+------------+-----------------+-------+
| 1 | 2020-09-04 11:02:00 | 400 | 0.1 | 400 | 1100 | 40.0 |
| 1 | 2020-09-04 12:05:00 | 500 | 0.2 | 900 | 600 | 100.0 |
| 1 | 2020-09-04 13:02:00 | 400 | 0.1 | 1300 | 200 | 40.0 |
| 1 | 2020-09-04 13:11:00 | 600 | 0.4 | 1900 | -400 | 80.0 |
| 1 | 2020-09-05 13:11:00 | 600 | 0.4 | 2500 | -1000 | 0.0 |
| 2 | 2020-09-04 10:01:00 | 300 | 0.3 | 300 | 1200 | 90.0 |
| 3 | 2020-09-04 11:02:00 | 700 | 0.2 | 700 | 800 | 140.0 |
+--------+---------------------+--------+------+------------+-----------------+-------+
我有 table 大致是这样的:
+--------+---------------------+--------+------+
| CustId | TransDate | Amount | Coef |
+--------+---------------------+--------+------+
| 1 | 2020-09-04 11:02:00 | 400 | 0.1 |
| 1 | 2020-09-04 12:05:00 | 500 | 0.2 |
| 1 | 2020-09-04 13:02:00 | 400 | 0.1 |
| 1 | 2020-09-04 13:11:00 | 600 | 0.4 |
| 2 | 2020-09-04 10:01:00 | 300 | 0.3 |
| 2 | 2020-09-04 11:02:00 | 700 | 0.2 |
+--------+---------------------+--------+------+
我想要实现的是给每个客户一个“奖金”,计算方式为金额 * 系数,但交易总额上限为 1,500。 “奖金”是针对 SUM <1,500 的客户交易授予的(按照交易进行的顺序)。
例如,客户“1”将在前 3 笔交易中获得全额赠金,在第 4 笔交易中获得 1,500 差价的赠金。基本上,最终结果应该是这样的:
+--------+---------------------+--------+------+---------------------------------------------------+
| CustId | TransDate | Amount | Coef | Bonus |
+--------+---------------------+--------+------+---------------------------------------------------+
| 1 | 2020-09-04 11:02:00 | 400 | 0.1 | 40 |
| 1 | 2020-09-04 12:05:00 | 500 | 0.2 | 100 |
| 1 | 2020-09-04 13:02:00 | 400 | 0.1 | 40 |
| 1 | 2020-09-04 13:11:00 | 600 | 0.4 | 80 /*(this is given only for the remaining 200)*/ |
| 2 | 2020-09-04 10:01:00 | 300 | 0.3 | 90 |
| 2 | 2020-09-04 11:02:00 | 700 | 0.2 | 140 |
+--------+---------------------+--------+------+---------------------------------------------------+
提前致谢!
干杯。
如果我没理解错的话,你想要一个累加和以及一些逻辑:
select t.*,
(case when sum(amount) over (partition by custid order by transdate) <= 1500
then coef * amount
when sum(amount) over (partition by custid order by transdate) - amount < 1500
then (1500 - sum(amount) over (partition by custid order by transdate)) as coef
else 0
end) as bonus
from t
[编辑]:现在使用 MAX 函数限制奖金金额。
数据
drop table if exists #tTEST;
go
select * INTO #tTEST from (values
(1, '2020-09-04 11:02:00', 400, 0.1),
(1, '2020-09-04 12:05:00', 500, 0.2),
(1, '2020-09-04 13:02:00', 400, 0.1),
(1, '2020-09-04 13:11:00', 600, 0.4),
(1, '2020-09-05 13:11:00', 600, 0.4),
(2, '2020-09-04 10:01:00', 300, 0.3),
(3, '2020-09-04 11:02:00', 700, 0.2)) V(CustId, TransDate, Amount, Coef);
查询
declare @bonus_limit int=1500;
with data_cte as (
select *, sum(amount) over (partition by custid order by transdate) cum_amount,
@bonus_limit-sum(amount) over (partition by custid order by transdate) cum_amount_diff
from #tTEST t)
select *,
(SELECT Max(v) FROM (VALUES (0), (case when cum_amount_diff<0 then (Amount+cum_amount_diff)*Coef
else Amount*Coef end)) AS value(v)) Bonus
from data_cte;
结果
+--------+---------------------+--------+------+------------+-----------------+-------+
| CustId | TransDate | Amount | Coef | cum_amount | cum_amount_diff | Bonus |
+--------+---------------------+--------+------+------------+-----------------+-------+
| 1 | 2020-09-04 11:02:00 | 400 | 0.1 | 400 | 1100 | 40.0 |
| 1 | 2020-09-04 12:05:00 | 500 | 0.2 | 900 | 600 | 100.0 |
| 1 | 2020-09-04 13:02:00 | 400 | 0.1 | 1300 | 200 | 40.0 |
| 1 | 2020-09-04 13:11:00 | 600 | 0.4 | 1900 | -400 | 80.0 |
| 1 | 2020-09-05 13:11:00 | 600 | 0.4 | 2500 | -1000 | 0.0 |
| 2 | 2020-09-04 10:01:00 | 300 | 0.3 | 300 | 1200 | 90.0 |
| 3 | 2020-09-04 11:02:00 | 700 | 0.2 | 700 | 800 | 140.0 |
+--------+---------------------+--------+------+------------+-----------------+-------+