有人要求我创建一份财务报告,其中需要为几个“推荐人”提供两个日期之间的总佣金率。这是简单的部分。
困难的部分是佣金率不仅取决于推荐人,而且还推荐类型以及推荐类型的推荐数量由给定的推荐人制作。
跟踪推荐数量需要考虑所有推荐,而不是给定日期范围内的推荐 - 换句话说,每个推荐人的佣金率都在 float 范围内,随着推荐总数的增加而变化。幸运的是,每种推荐类型最多只有 3 个佣金级别。
推荐都存储在同一个表中,每个推荐 1 行,其中一个字段表示推荐人和推荐类型。举例说明:
ID Type Referrer Date
1 A X 01/12/08
2 A X 15/01/09
3 A X 23/02/09
4 B X 01/12/08
5 B X 15/01/09
6 A Y 01/12/08
7 A Y 15/01/09
8 B Y 15/01/09
9 B Y 23/02/09
佣金率不存储在推荐表中——实际上可能会改变——而是存储在推荐表中,如下所示:
Referrer Comm_A1 Comm_A2 Comm_A3 Comm_B1 Comm_B2 Comm_B3
X 30 20 10 55 45 35
Y 45 35 25 60 40 30
以上述推荐表为例,假设佣金率水平在推荐编号 1 和 2 之后增加(然后保持不变),运行 2008 年 12 月至 2009 年 2 月的佣金报告将返回以下内容:
[编辑] - 为了澄清以上内容,佣金率针对每种类型和每个推荐人分为三个级别,第一个推荐佣金的初始费率 Comm_A1,然后是第二个佣金的 Comm_A2,以及所有后续推荐的 Comm_A3。
Referrer Type_A_Comm Type_A_Ref Type_B_Comm Type_B_Ref
X 60 3 100 2
Y 80 2 100 2
仅运行 2009 年 2 月的佣金报告将返回:
Referrer Type_A_Comm Type_A_Ref Type_B_Comm Type_B_Ref
X 10 1 0 0
Y 0 0 40 1
编辑 根据列/行分组,以上结果已根据我的原始问题进行了调整。
我很确定任何解决方案都将涉及子查询(可能针对每种推荐类型)以及某种聚合/Sum If - 但我正在努力想出一个有效的查询。
[编辑] 我不确定是否要写出我的要求的等式,但我会尝试列出我看到的步骤:
确定每种类型和每个引荐来源的先前引荐数量 - 也就是说,不考虑任何日期范围。
根据之前推荐的数量,选择合适的佣金级别 - 0 previous = level 1, 1 previous = level 2, 2 or more previous = level 3
(注意:没有以前推荐但有 3 个新推荐的推荐人期望佣金为 1 x 级别 1、1 x 级别 2、1 x 级别 3 = 总佣金)
根据日期范围过滤结果 - 以便可以确定针对某段事件的应付佣金。
返回包含推荐人列的数据,以及包含每种推荐类型的总佣金的列(理想情况下,还有包含每种推荐类型的计数的列)。
这有助于阐明我的要求吗?
最佳答案
假设您有一个名为 type
的表,其中列出了您的特定引荐类型,这应该可行(如果不行,您可以用另一个子选择来替代从引荐中获取不同的类型)。
select
r.referrer,
t.type,
(case
when isnull(ref_prior.referrals, 0) < @max1 then
(case
when isnull(ref_prior.referrals, 0) + isnull(ref_period.referrals, 0) < @max1 then isnull(ref_period.referrals, 0)
else @max1 - isnull(ref_prior.referrals, 0)
end)
else 0
end) * (case t.type when 'A' then r.Comm_A1 when 'B' then r.Comm_B1 else null end) +
(case when isnull(ref_prior.referrals, 0) + isnull(ref_period.referrals, 0) > @max1 then
(case
when isnull(ref_prior.referrals, 0) < @max2 then
(case
when isnull(ref_prior.referrals, 0) + isnull(ref_period.referrals, 0) < @max2 then isnull(ref_period.referrals, 0)
else @max2 - isnull(ref_prior.referrals, 0)
end)
else 0
end) -
(case
when isnull(ref_prior.referrals, 0) < @max1 then
(case
when isnull(ref_prior.referrals, 0) + isnull(ref_period.referrals, 0) < @max1 then isnull(ref_period.referrals, 0)
else @max1 - isnull(ref_prior.referrals, 0)
end)
else 0
end)
else 0 end) * (case t.type when 'A' then r.Comm_A2 when 'B' then r.Comm_B2 else null end) +
(case when isnull(ref_prior.referrals, 0) + isnull(ref_period.referrals, 0) > @max2 then
(isnull(ref_period.referrals, 0)) -
(
(case when isnull(ref_prior.referrals, 0) + isnull(ref_period.referrals, 0) > @max1 then
(case
when isnull(ref_prior.referrals, 0) < @max2 then
(case
when isnull(ref_prior.referrals, 0) + isnull(ref_period.referrals, 0) < @max2 then isnull(ref_period.referrals, 0)
else @max2 - isnull(ref_prior.referrals, 0)
end)
else 0
end) -
(case
when isnull(ref_prior.referrals, 0) < @max1 then
(case
when isnull(ref_prior.referrals, 0) + isnull(ref_period.referrals, 0) < @max1 then isnull(ref_period.referrals, 0)
else @max1 - isnull(ref_prior.referrals, 0)
end)
else 0
end)
else 0 end) +
(case
when isnull(ref_prior.referrals, 0) < @max1 then
(case
when isnull(ref_prior.referrals, 0) + isnull(ref_period.referrals, 0) < @max1 then isnull(ref_period.referrals, 0)
else @max1 - isnull(ref_prior.referrals, 0)
end)
else 0
end)
)
else 0 end) * (case t.type when 'A' then r.Comm_A3 when 'B' then r.Comm_B3 else null end) as Total_Commission
from referrer r
join type t on 1 = 1 --intentional cartesian product
left join (select referrer, type, count(1) as referrals from referral where date < @start_date group by referrer, type) ref_prior on ref_prior.referrer = r.referrer and ref_prior.type = t.type
left join (select referrer, type, count(1) as referrals from referral where date between @start_date and @end_date group by referrer, type) ref_period on ref_period.referrer = r.referrer and ref_period.type = t.type
这假设您有一个 @start_date
和 @end_date
变量,并且您显然必须提供 case 语句中缺少的逻辑才能做出正确的选择基于 ref_total 的推荐类型和数量的费率。
编辑
看完问题后,我看到了关于滑动比例的评论。这大大增加了查询的复杂性,但它仍然是可行的。修改后的查询现在还取决于两个变量 @max1
和 @max2
的存在,代表可以属于类别“1”和类别“2”的最大销售数量'(出于测试目的,我分别使用了 1 和 2,它们产生了预期的结果)。
关于MySQL 高级查询脑筋急转弯,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/803597/