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とすべての可能な月(2012年1月1日、2012年1月2日などから現在まで)の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を使用して要約レポートを生成する方法を示しています。営業担当者は、該当する売上がない場合、結果から除外されます。

より多くの娯楽のために@RollingMonths、レポートパラメータを揺さぶってみてください。1

-- 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

これが1つの解決策です:

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 に答える
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 に答える