0

假设我有一个表格,显示每个销售代表在特定月份销售的商品数量。但是,在没有销售的月份内,不会有针对特定人员的排行。例子

rep_id     month_yr     num_sales    
1          01/01/2012    3    
1          05/01/2012    1    
1          11/01/2012    1    
2          02/01/2012    2    
2          05/01/2012    1  

我希望能够创建一个查询,显示每个 rep_id 和所有可能的月份(01/01/2012、02/01/2012 等到当前)滚动 12 个月的销售额,如下所示:

rep_id     month_yr     R12_Sum    
1          11/01/2012   5    
1          12/01/2012   5    
1          01/01/2013   5    
1          02/01/2013   2

我在网上找到了一些例子,但我遇到的问题是我错过了每个 rep_id 的一些日期。我需要交叉加入还是什么?

4

4 回答 4

2

要解决这个问题,您需要一个包含所有年/月组合的驱动程序表。然后,您需要为每个代表创建这个。

然后解决方案是将实际数据左连接到此驱动程序并聚合您想要的时间段。这是查询:

with months as (
    select 1 as mon union all select 2 union all select 3 union all select 4 union all
    select 5 as mon union all select 6 union all select 7 union all select 8 union all
    select 9 as mon union all select 10 union all select 11 union all select 12
   ),
    years as (select 2010 as yr union all select 2011 union all select 2012 union all select 2013
   ),
    monthyears as (
     select yr, mon, yr*12+mon as yrmon
     from months cross join years
    ),
     rmy as (
     select *
     from monthyears my cross join
          (select distinct rep_id from t
          ) r
    )
select rmy.rep_id, rmy.yr, rmy.mon, SUM(t.num_sales) as r12_sum
from rmy join
     t
     on rmy.rep_id = t.rep_id and
        t.year(month_yr)*12 + month(month_yr) between rmy.yrmon - 11 and rmy.yrmon
group by rmy.rep_id, rmy.yr, rmy.mon
order by 1, 2, 3  

这还没有经过测试,所以它可能有语法错误。此外,它不会将年/月组合转换回日期,而是将值留在单独的列中。

于 2013-03-21T15:50:46.560 回答
0

下面演示了使用 CTE 生成日期表并使用 CTE 生成摘要报告。当销售代表没有适用的销售额时,他们会从结果中省略。

尝试调整报告参数,例如设置@RollingMonths1,以获得更多乐趣。

-- Sample data.
declare @Sales as Table ( rep_id Int, month_yr Date, num_sales Int );
insert into @Sales ( rep_id, month_yr, num_sales ) values
  ( 1, '01/01/2012', 3 ),
  ( 1, '05/01/2012', 1 ),
  ( 1, '11/01/2012', 1 ),
  ( 2, '02/01/2012', 1 ),
  ( 2, '05/01/2012', 2 );
select * from @Sales;

-- Reporting parameters.
declare @ReportEnd as Date = DateAdd( day, 1 - Day( GetDate() ), GetDate() ); -- The first of the current month.
declare @ReportMonths as Int = 6; -- Number of months to report.
declare @RollingMonths as Int = 12; -- Number of months in rolling sums.

-- Report.
--   A CTE generates a table of month/year combinations covering the desired reporting time period.
with ReportingIntervals as (
  select DateAdd( month, 1 - @ReportMonths, @ReportEnd ) as ReportingInterval,
    DateAdd( month, 1 - @RollingMonths, DateAdd( month, 1 - @ReportMonths, @ReportEnd ) ) as FirstRollingMonth
  union all
  select DateAdd( month, 1, ReportingInterval ), DateAdd( month, 1, FirstRollingMonth )
    from ReportingIntervals
    where ReportingInterval < @ReportEnd )
  -- Join the CTE with the sample data and summarize.
  select RI.ReportingInterval, S.rep_id, Sum( S.num_sales ) as R12_Sum
    from ReportingIntervals as RI left outer join
      @Sales as S on RI.FirstRollingMonth <= S.month_yr and S.month_yr <= RI.ReportingInterval
    group by RI.ReportingInterval, S.rep_id
    order by RI.ReportingInterval, S.rep_id
于 2013-03-21T17:24:59.707 回答
0

它当然不漂亮,但比 CTE、数字表或自连接更简单:

DECLARE @startdt DATETIME

SET @startdt = '2012-01-01'

SELECT rep_id, YEAR(month_yr), MONTH(month_yr), SUM(num_sales)
FROM MyTable WHERE month_yr >= @startdt AND month_yr < DATEADD(MONTH,1,@startdt)

UNION ALL

SELECT rep_id, YEAR(month_yr), MONTH(month_yr), SUM(num_sales)
FROM MyTable WHERE month_yr >= DATEADD(MONTH,1,@startdt) AND month_yr < DATEADD(MONTH,2,@startdt)

UNION ALL

SELECT rep_id, YEAR(month_yr), MONTH(month_yr), SUM(num_sales)
FROM MyTable WHERE month_yr >= DATEADD(MONTH,2,@startdt) AND month_yr < DATEADD(MONTH,3,@startdt)

UNION ALL

SELECT rep_id, YEAR(month_yr), MONTH(month_yr), SUM(num_sales)
FROM MyTable WHERE month_yr >= DATEADD(MONTH,3,@startdt) AND month_yr < DATEADD(MONTH,4,@startdt)

UNION ALL

etc etc
于 2013-03-21T16:14:10.750 回答
0

这是一种解决方案:

SELECT 
  a.rep_id
  ,a.month_yr
  ,SUM(b.R12_Sum) AS R12_TTM
FROM YourTable a
  LEFT OUTER JOIN YourTable b 
    ON a.rep_id = b.rep_id
    AND a.month_yr <= b.month_yr
    AND a.month_yr >= DATEADD(MONTH, -11, b.month_yr)
GROUP BY
  a.rep_id
  ,a.month_yr
于 2013-03-21T15:10:28.873 回答