MySQL 高级查询脑筋急转弯

标签 mysql sql

有人要求我创建一份财务报告,其中需要为几个“推荐人”提供两个日期之间的总佣金率。这是简单的部分。

困难的部分是佣金率不仅取决于推荐人,而且推荐类型以及推荐类型的推荐数量由给定的推荐人制作。

跟踪推荐数量需要考虑所有推荐,而不是给定日期范围内的推荐 - 换句话说,每个推荐人的佣金率都在 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/

相关文章:

Java Spring 错误 : Could not get JDBC Connection

php - 从 DATETIME 列 MySQL/PHP 中检索时间间隔的数据

sql - 分析sql死锁xml

macos - MAMP 出现异常 MySql 错误

php - 在 mysql 中显示开始日期和结束日期之间的日期

SQL Server : How to perform Rtrim on all varchar columns of a table

mysql - 统计MySQL中的两个表,并根据另一个表的日期显示结果

sql - Azure ASP.Net MVC 数据库部署最佳实践

sql - 如何在不编写函数的情况下在 SQL Server 中提取 URL 查询字符串参数?

MySQL 从列中返回可能的对