1

次のようなPROJECTNAME、ACTUALCOST、PROJECTSTART、およびPROJECTEND列を持つテーブルがあります。

PROJECTNAME          ACTUAL COST          PROJECTSTART          PROJECTEND
abc                  1500                 2011-12-01            2012-07-31
prj1                 1170                 2012-01-09            2012-06-30  
xyz                  5350                 2012-01-30            2012-03-30

私は以下のような出力を取得しようとしています:

PRJNAME     DEC11     JAN12     FEB12     MAR12     APR12     MAY12     JUN12     JUL12 ...
abc         187.5     187.5     187.5     187.5     187.5     187.5     187.5     187.5
prj1                  117       195       195       195       195       195

毎月の残り日数に応じて、各プロジェクト名の毎月のコスト内訳が必要です。

4

1 に答える 1

1

PIVOTこの関数を 使用して結果を取得できます。

これを行うことをお勧めする方法は、最初にこれのハードコードされたバージョンを記述し、次にそれを動的SQLに変換することです。

Actual Cost注:1か月あたりのコストは、projectstart/projectendの間の1日あたりの日数で割って決定しました。これにより、少なくとも実際のレポートを開始できるはずです。

静的バージョンは次のようになります。

;with cte as
(
  select projectname, [ACTUAL COST], [PROJECTSTART], [PROJECTEND]
  from yourtable
  union all
  select projectname, [ACTUAL COST], 
    dateadd(d, 1, PROJECTSTART),
    PROJECTEND
  from cte
  where dateadd(d, 1, PROJECTSTART) <= ProjectEnd
) 
select *
from
(
  select 
    my.projectname,
    my.monthyear,
    my.totaldayspermonth * a.perdaycost AmountPerMonth
  from
  (
    select projectname,
    left(datename(m, projectstart), 3) + cast(year(projectstart) as varchar(4)) monthyear,
    count(*) TotalDaysPerMonth
    from cte
    group by projectname,
      [actual cost],
      left(datename(m, projectstart), 3) + cast(year(projectstart) as varchar(4))
  ) my
  cross apply
  (
    select projectname, 
      round([actual cost] / (datediff(d, projectstart, projectend) *1.0), 2) PerDayCost
    from yourtable a
    where my.projectname = a.projectname
  ) a
) src
pivot
(
  max(AMOUNTPERMONTH)
  for monthyear in (Dec2011, Jan2012, Feb2012, Mar2012,
                    Apr2012, May2012, Jun2012, Jul2012, Aug2012)
) piv
OPTION(MAXRECURSION 0);

SQL FiddlewithDemoを参照してください。

静的バージョンを入手すると、動的SQLへの変換がはるかに簡単になります。動的SQLは次のようになります。

;with cte as
(
  select projectname, [ACTUAL COST], [PROJECTSTART], [PROJECTEND]
  from yourtable
  union all
  select projectname, [ACTUAL COST], 
    dateadd(d, 1, PROJECTSTART),
    PROJECTEND
  from cte
  where dateadd(d, 1, PROJECTSTART) <= ProjectEnd
) 
select *
into #dates
from cte
OPTION(MAXRECURSION 0)

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT ',' + QUOTENAME(left(datename(m, projectstart), 3) + cast(year(projectstart) as varchar(4))) 
                    from #dates
                    group by datename(m, projectstart), year(projectstart), month(projectstart)
                    order by year(projectstart), month(projectstart)
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = ';with cte as
              (
                select projectname, [ACTUAL COST], [PROJECTSTART], [PROJECTEND]
                from yourtable
                union all
                select projectname, [ACTUAL COST], 
                  dateadd(d, 1, PROJECTSTART),
                  PROJECTEND
                from cte
                where dateadd(d, 1, PROJECTSTART) <= ProjectEnd
              ) 
              select projectname, '+@cols+' 
              from
              (
                select 
                  my.projectname,
                  my.monthyear,
                  my.totaldayspermonth * a.perdaycost AmountPerMonth
                from
                (
                  select projectname,
                  left(datename(m, projectstart), 3) + cast(year(projectstart) as varchar(4)) monthyear,
                  count(*) TotalDaysPerMonth
                  from cte
                  group by projectname,
                    [actual cost],
                    left(datename(m, projectstart), 3) + cast(year(projectstart) as varchar(4))
                ) my
                cross apply
                (
                  select projectname, 
                    round([actual cost] / (datediff(d, projectstart, projectend) *1.0), 2) PerDayCost
                  from yourtable a
                  where my.projectname = a.projectname
                ) a
              ) src
              pivot
              (
                max(AMOUNTPERMONTH)
                for monthyear in ('+@cols+')
              )piv
              OPTION(MAXRECURSION 0)'

execute(@query)

SQL FiddlewithDemoを参照してください

両方のクエリの結果は次のとおりです。

| PROJECTNAME | DEC2011 | JAN2012 | FEB2012 | MAR2012 | APR2012 | MAY2012 | JUN2012 | JUL2012 |
-----------------------------------------------------------------------------------------------
|         abc |  191.27 |  191.27 |  178.93 |  191.27 |   185.1 |  191.27 |   185.1 |  191.27 |
|        prj1 |  (null) |  155.48 |  196.04 |  209.56 |   202.8 |  209.56 |   202.8 |  (null) |
|         xyz |  (null) |  178.34 | 2585.93 |  2675.1 |  (null) |  (null) |  (null) |  (null) |
于 2013-02-20T01:43:45.577 に答える