2

我有一个如下表设置:

客户名称每月资源成本
abc JAN2011 res1 1000
美国广播公司 FEB2011 res1 2000
def JAN2011 res2 1500
def MAR2011 res1 2000
吉 MAR2011 res3 2500

我需要一个像下面这样的输出。月份将以 3 个月为间隔动态生成。在这种情况下,有没有办法按 MONTHANDYEAR 以及按客户名分组?

资源客户名称 2011 年 1 月 2011 年 2 月 2011 年 3 月   
res1 abc 1000 1000
res1 def 2000
res2 分辨率 1500
res3 吉 2500
4

3 回答 3

3

这就是 PIVOT 运算符的用途:

SELECT 
  Resource, ClientName,
  [JAN2011], [FEB2011], [MAR2011]
FROM
  (
  SELECT 
    *  
  FROM tblname
  ) AS SourceTable
PIVOT
  (
  SUM(COST)
  FOR MONTHANDYEAR IN ([JAN2011], [FEB2011], [MAR2011])
  ) AS PivotTable;

由于您的月份是使用 @startDate 作为基准月份动态选择的,因此您可以使用以下动态查询:

DECLARE @startDate datetime
SET @startDate = '2011-01-01'

DECLARE @sql varchar(MAX)
SET @sql = 'SELECT
        Resource, ClientName, [' +
          REPLACE(SUBSTRING(CONVERT(varchar, @startDate, 13), 4, 8), ' ', '') + '], [' +
          REPLACE(SUBSTRING(CONVERT(varchar, DATEADD(MONTH, 1, @startDate), 13), 4, 8), ' ', '') + '], [' +
          REPLACE(SUBSTRING(CONVERT(varchar, DATEADD(MONTH, 2, @startDate), 13), 4, 8), ' ', '') + ']
        FROM
          (
          SELECT
            *
          FROM tblName
          ) AS SourceTable
        PIVOT
          (
          SUM(COST)
          FOR MONTHANDYEAR IN (' +
                  QUOTENAME(REPLACE(SUBSTRING(CONVERT(varchar, @startDate, 13), 4, 8), ' ', '')) + ', ' +
                  QUOTENAME(REPLACE(SUBSTRING(CONVERT(varchar, DATEADD(MONTH, 1, @startDate), 13), 4, 8), ' ', '')) + ', ' +
                  QUOTENAME(REPLACE(SUBSTRING(CONVERT(varchar, DATEADD(MONTH, 2, @startDate), 13), 4, 8), ' ', '')) + ')
          ) AS PivotTable'

execute(@sql)

在这里工作sqlfiddle

于 2013-02-22T04:32:50.960 回答
1

可以使用该PIVOT函数完成此数据转换。

如果您知道这些值,则可以对monthandyear日期进行硬编码:

select resource,
  clientname,
  isnull(jan2011, '') Jan2011,
  isnull(feb2011, '') Feb2011,
  isnull(mar2011, '') Mar2011
from
(
  select clientname, monthandyear, resource, cost
  from yourtable
) src
pivot
(
  sum(cost)
  for monthandyear in (Jan2011, Feb2011, Mar2011)
) piv;

请参阅SQL Fiddle with Demo

但如果日期未知,则需要使用动态 SQL:

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

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(monthandyear) 
                    from yourtable
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

select @colNames = STUFF((SELECT distinct ', isnull(' + QUOTENAME(monthandyear)+', 0) as '+QUOTENAME(monthandyear)
                    from yourtable
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')


set @query = 'SELECT resource, clientname,' + @colNames + ' from 
             (
                select clientname, monthandyear, resource, cost
                from yourtable
            ) x
            pivot 
            (
                sum(cost)
                for monthandyear in (' + @cols + ')
            ) p '

execute(@query)

请参阅SQL Fiddle with Demo

两者的结果是:

| RESOURCE | CLIENTNAME | JAN2011 | FEB2011 | MAR2011 |
-------------------------------------------------------
|     res1 |        abc |    1000 |    2000 |       0 |
|     res1 |        def |       0 |       0 |    2000 |
|     res2 |        def |    1500 |       0 |       0 |
|     res3 |        ghi |       0 |       0 |    2500 |
于 2013-02-22T12:46:39.107 回答
0
SELECT Resource, Clientname
, SUM(CASE WHEN MonthAndYear = 'JAN2011' THEN COST ELSE 0 END) AS JAN2011
, SUM(CASE WHEN MonthAndYear = 'FEB2011' THEN COST ELSE 0 END) AS FEB2011
, SUM(CASE WHEN MonthAndYear = 'MAR2011' THEN COST ELSE 0 END) AS MAR2011
FROM yourtable
GROUP BY Resource, Clientname

您还可以删除ELSE 0以返回NULL没有数据的资源/客户端名称组合的值

于 2013-02-22T04:26:36.530 回答