2013-02-22 76 views
2

我有一个表设置象下面这样:SQL动态枢轴和组导致

CLIENTNAME   MONTHANDYEAR  RESOURCE  COST 
abc     JAN2011   res1   1000 
abc     FEB2011   res1   2000 
def     JAN2011   res2   1500 
def     MAR2011   res1   2000 
ghi     MAR2011   res3   2500

我需要的输出像的下方。几个月将在3个月的时间间隔内动态生成。在这种情况下,有没有办法通过MONTHANDYEAR以及按客户端名称进行分组?

RESOURCE CLIENTNAME  JAN2011  FEB2011  MAR2011 
res1  abc   1000   1000 
res1  def          2000 
res2  def   1500 
res3  ghi          2500 
+0

这里面有多少已经* *在该数据库上完成结束?例如,您可以在客户端应用程序中构建您的查询吗?或者您是否使用可以进行数据透视/分组的报告解决方案? – 2013-02-22 04:20:26

+0

我们的报告软件具有非常有限的功能,不能像上述那样转置数据。 – 0onetwo 2013-02-22 04:22:21

回答

1

这是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 here

+0

@ 0onetwo,根据您的规格进行动态查询更新 – PinnyM 2013-02-22 14:45:12

+0

这真棒。感谢堆。 – 0onetwo 2013-02-25 00:37:15

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返回资源/ CLIENTNAME组合一个NULL值没有数据

+0

非常感谢,但我应该补充说,这些月份需要动态生成,每次三个月。 – 0onetwo 2013-02-22 04:32:44

+0

@ 0onetwo,你可以通过这些月份名作为参数,或单个参数逗号分隔的列表? – PinnyM 2013-02-22 04:36:01

+0

开始的月份将作为参数传入,查询将执行该月和接下来两个月的计算。 – 0onetwo 2013-02-22 04:48:20

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:

​​

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

非常感谢。我希望我可以给你勾选为好,但PinnyM的回答为我工作好一点。 – 0onetwo 2013-02-25 00:36:43

+0

@ 0onetwo投票赞同! :) – Taryn 2013-02-25 00:38:28