我被要求创建一份财务报告,需要在几个“推荐人”的两个日期之间提供总佣金率。这很容易。
困难的部分是佣金率不仅取决于推荐人,而且也关于推荐类型以及对该类推荐人数的影响已由特定推荐人制作。
跟踪推荐人数需要考虑所有推荐,而不是指定日期范围内的推荐 - 换句话说,每个推荐人的佣金率都在滑动范围内,随着推荐总数的增加而变化。幸运的是,每种推荐类型最多只有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
修改上述结果已根据我的原始问题进行了调整,就列/行分组而言。
我很确定任何解决方案都会涉及一个子查询(可能是针对每个推荐类型)以及某种聚合/总和如果 - 但我正在努力想出一个有效的查询。
[编辑] 我不确定是否要写出我的要求的等式,但我会尝试列出我看到的步骤:
确定每种类型和每个推荐人的先前推荐数量 - 也就是说,无论日期范围如何。
根据之前推介的数量,选择适当的佣金等级 - 0先前=等级1,1先前=等级2,2或更高之前=等级3
(注意:推荐人没有以前的推荐,但是,例如,3个新的推荐人,预计佣金为1 x 1级,1 x 2级,1 x 3级=总佣金)
根据日期范围过滤结果 - 以便确定一段活动的应付佣金。
返回带有referrer列的数据,以及一个包含每个推介类型总佣金的列(理想情况下,还有一个每个推荐类型都有一个计数的列)。
这有助于澄清我的要求吗?
答案 0 :(得分:4)
假设您有一个名为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,这些产生了预期的结果)。
答案 1 :(得分:2)
亚当的回答远比我想要的要彻底,但我认为尝试将其作为单一查询来写可能不是正确的方法。
您是否考虑过创建一个存储过程,然后逐步创建并填充临时表。
临时表将具有您正在寻找的结果集的形状。初始插入创建基本数据集(基本上是您希望返回的行数,包含键标识符,然后是您希望返回的任何其他内容,可以轻松地将其组合为同一查询的一部分)。
然后,您可以对临时表进行一系列更新,以组合更复杂数据的每个部分。
最后选择全部然后放下临时表。
这样做的好处是它可以让你在脑海中分解并稍微组装一下,这样你就可以更容易地找到出错的地方。这也意味着可以在几个阶段组装更复杂的位。
此外,如果一些可怜的草皮出现并且之后必须调试整个事情,那么他将更容易追踪发生在哪里的事情。
答案 2 :(得分:0)
编辑:这个答案没有考虑到以下要求,但似乎有一堆新的解释,所以我想我会把它留在这里......
跟踪引荐数量需要考虑所有引荐,而不是指定日期范围内的引荐
好的,假设报告期是每月一次,并使用CASE实际上IF可以区分两个有效费率(对于count = 1和count&gt; 1),那么:
select
ref.month,
ref.referrer,
ref.type,
( ref.count *
case ref.type
when 'A' then
case ref.count
-- not useful: when 0 then com.Comm_A1
when 1 then com.Comm_A2
else com.Comm_A3
end case
when 'B' then
case ref.count
-- not useful: when 0 then com.Comm_B1
when 1 then com.Comm_B2
else com.Comm_B3
end case
end case
) as total_commission
from
( select
date_format(date, '%Y-%m') as month,
referrer,
type,
count(*) as count
from referrals
group by month, referrer, type
) as ref,
join commissions com on com.referrer = ref.referrer
(我猜上面没有选择'ref'和'count'等名称。)