SQL:根据连续记录的存在进行计算

时间:2019-11-19 16:06:01

标签: sql-server

我正在建立奖金,该奖金根据许多标准来计算我们的销售团队的资格,其中最具挑战性的部分是在连续三个月内实现总价值的标准。

以下是我到目前为止(除其他标准外)用于计算此奖金的信息:

select customer
    ,salesperson
    ,year
    ,month
    ,gm
    ,Appearance_Count
    ,case
        when appearance_count between 1 and 6 then 'Y' end as 'First 6'
    ,case
        when gm >= 150 then 'Y' end as 'Monthly Min'
from basedata 

到目前为止的结果集:

enter image description here

  • 月份代表期间(这是给定月份内的任何销售)
  • gm是金额
  • ,我创建了编号为计数器的计数器来表示客户存在了多少个月。
  • 在第一笔CASE声明中,AC在1到6之间定义,表示奖金仅适用于与我们同在的客户,即他们是我们客户的前6个月内。
  • 第二个案例表明,要激活资格,每月必须至少有GM 150。

因此,我在挣扎的地方还需要考虑到,连续3个月(在6个月内)必须有总计2400 GM的收入。计算连续3个月的周期最简单的方法是什么?


更新1:这是我希望看到的示例。

customer  salesperson   yr  mon gm      AC   1st 6  Mon/Min  3-mo-consec
3D PAVING   Ryan      2019  8   1771.67    1    Y     Y         N
3D PAVING   Ryan      2019  9   1169.19    2    Y     Y         N
3D PAVING   Ryan      2019  10  1132.07    3    Y     Y         Y
3D PAVING   Ryan      2019  11  585.99     4    Y     Y         N

1 个答案:

答案 0 :(得分:0)

您可能可以通过一系列自联接来完成此操作,但是对于大量数据而言,它并不会很快,因为它需要在JOIN条件下进行一些算术运算,这意味着无法使用索引。如果这不是问题(我想如果要创建要偶尔生成的报告就不是问题),则以下查询应该会有所帮助。

abc分别代表连续3个月中的第一,第二和第三个月。您可以将每一行连接到下一行,条件是它是同一年的下个月,或者第一行是X年的12月,第二行是X + 1的一月。然后可以将{{1 }}中的每条连接记录,并对照2400的边界对其进行检查。

gm

这只会获取three_month_aggregate条件,因此您必须单独运行它或将结果加入到原始查询中。您可以这样做:

SELECT WHEN a.gm + b.gm + c.gm > 2400 THEN 'Y' END AS three_month_aggregate
FROM basedata a
INNER JOIN basedata b
    ON a.customer = b.customer
    AND a.salesperson = b.salesperson
    AND (
        (a.year = b.year AND a.month = b.month - 1)
        OR (a.year = b.year - 1 AND a.month = 12 AND b.month = 1)
    )
INNER JOIN basedata c
    ON b.customer = c.customer
    AND b.salesperson = c.salesperson
    AND (
        (b.year = c.year AND b.month = c.month - 1)
        OR (b.year = c.year - 1 AND b.month = 12 AND c.month = 1)
    )

编辑-如果您只希望在三个月的记录之一中显示“ Y”,则可以在查询结束时删除相应的JOIN条件。我专门设计了它,以便在连续三个月中的每个月都给它一个“ Y”,但是例如,如果您只希望列表中第一个月为“ Y”,则可以更改最终的JOIN条件在查询中:

SELECT customer
    ,salesperson
    ,year
    ,month
    ,gm
    ,Appearance_Count
    ,CASE
        WHEN appearance_count BETWEEN 1 AND 6 THEN 'Y' END AS 'First 6'
    ,CASE
        WHEN gm >= 150 THEN 'Y' END AS 'Monthly Min'
    ,tma.three_month_aggregate AS 'Three Month Aggregate'
FROM basedata i
INNER JOIN (
    SELECT WHEN a.gm + b.gm + c.gm > 2400 THEN 'Y' END AS three_month_aggregate
    FROM basedata a
    INNER JOIN basedata b
        ON a.customer = b.customer
        AND a.salesperson = b.salesperson
        AND (
            (a.year = b.year AND a.month = b.month - 1)
            OR (a.year = b.year - 1 AND a.month = 12 AND b.month = 1)
        )
    INNER JOIN basedata c
        ON b.customer = c.customer
        AND b.salesperson = c.salesperson
        AND (
            (b.year = c.year AND b.month = c.month - 1)
            OR (b.year = c.year - 1 AND b.month = 12 AND c.month = 1)
        )
) tma ON (
    (i.customer = a.customer AND i.salesperson = a.salesperson)
    OR (i.customer = b.customer AND i.salesperson = b.salesperson)
    OR (i.customer = c.customer AND i.salesperson = c.salesperson)
)

注意:这确实意味着现在只有该月份出现在您的总体结果中。如果您仍然希望所有月份都显示出来,请使用LEFT JOIN而不是INNER JOIN来对) tma ON ( (i.customer = a.customer AND i.salesperson = a.salesperson) # removed JOIN to b and c, the second and third months in the chain ) 子查询进行联接。