This seems like a simple thing to accomplish but I'm not sure if I am thinking about it correctly to get the desired results. I'm using a pivot but I think I need something else paired with it.
I have an invoice table that contains monthly invoices for each client. At most, a client will have 12 invoices per year, 1 for each month.
+----------+-------+-------+--------------+--------------+--------------+
| ClientID | Month | Year  | ColumnValue1 | ColumnValue2 | ColumnValue3 |
+----------+-------+-------+--------------+--------------+--------------+
|        1 |     1 |  2012 |           20 |           30 |           50 |
|        1 |     2 |  2012 |           25 |           35 |           40 |
|        2 |     1 |  2012 |           28 |           38 |           48 |
+----------+-------+-------+--------------+--------------+--------------+
Now, I want to create a list like below based on each client. There would be a column for each month. So Client 1 would look like:
+--------------+----+----+---+---+---+---+---+---+---+----+----+----+-------+
|  ColumnName  | 1  | 2  | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Total |
+--------------+----+----+---+---+---+---+---+---+---+----+----+----+-------+
| ColumnValue1 | 20 | 25 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |  0 |  0 |  0 |   45  |
| ColumnValue2 | 30 | 35 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |  0 |  0 |  0 |   65  |
| ColumnValue3 | 50 | 40 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |  0 |  0 |  0 |   90  |
+--------------+----+----+---+---+---+---+---+---+---+----+----+----+-------+
                This can be done using both the UNPIVOT and PIVOT function in SQL Server.  If you have a known number of columns, then you can use a static version:
select clientid,
  col, year,
  isnull([1], 0) [1], 
  isnull([2], 0) [2], 
  isnull([3], 0) [3], 
  isnull([4], 0) [4], 
  isnull([5], 0) [5], 
  isnull([6], 0) [6], 
  isnull([7], 0) [7], 
  isnull([8], 0) [8], 
  isnull([9], 0) [9], 
  isnull([10], 0) [10], 
  isnull([11], 0) [11], 
  isnull([12], 0) [12],
  (isnull([1], 0) + isnull([2], 0) + isnull([3], 0) 
   + isnull([4], 0) + isnull([5], 0) + isnull([6], 0) 
   + isnull([7], 0) + isnull([8], 0) + isnull([9], 0) 
   + isnull([10], 0) + isnull([11], 0) + isnull([12], 0) ) Total
from
(
  select clientid, col, month, year, value
  from yourtable
  unpivot
  (
    value for col in (ColumnValue1, ColumnValue2, ColumnValue3)
  ) u
) x
pivot
(
  sum(value)
  for month in ([1], [2], [3], [4], [5], [6], [7], 
                [8], [9], [10], [11], [12])
) p
See SQL Fiddle with Demo
But it might be considerably easier to use dynamic sql to perform this operation, then there is less code to write and this will adjust the number of months based on what you have in your data sample:
DECLARE @colsUnpivot AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX),
    @colsPivot as  NVARCHAR(MAX),
    @colsTotal as  NVARCHAR(MAX),
    @colsNull as  NVARCHAR(MAX)
select @colsUnpivot = stuff((select ','+ quotename(C.name)
         from sys.columns as C
         where C.object_id = object_id('yourtable') and
               C.name like 'ColumnValue%'
         for xml path('')), 1, 1, '')
select @colsPivot = STUFF((SELECT distinct ', '  + quotename(Month)
                    from yourtable t
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')
select @colsNull = STUFF((SELECT distinct ', IsNull(' 
                           + quotename(Month) + ', 0) as '+quotename(Month)
                    from yourtable t
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')
select @colsTotal = STUFF((SELECT distinct '+ IsNull(' 
                           + quotename(Month) + ', 0)'
                    from yourtable t
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')
set @query 
  = 'select clientid,
          year,
          '+@colsNull+', '+@colsTotal+' as Total
      from
      (
        select clientid, col, month, year, value
        from yourtable
        unpivot
        (
          value for col in ('+@colsUnpivot+')
        ) u
      ) x
      pivot
      (
        sum(value)
        for month in('+ @colspivot +')
      ) p'
exec(@query)
See SQL Fiddle with Demo
Both will produce the same results, the difference is that the second will adjust based on the data in your table:
| CLIENTID | YEAR |  1 |  2 | TOTAL |
-------------------------------------
|        1 | 2012 | 20 | 25 |    45 |
|        1 | 2012 | 30 | 35 |    65 |
|        1 | 2012 | 50 | 40 |    90 |
|        2 | 2012 | 28 |  0 |    28 |
|        2 | 2012 | 38 |  0 |    38 |
|        2 | 2012 | 48 |  0 |    48 |
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With