2014-10-06 25 views
2

我正在使用SQL Server 2008 R2和T-SQL。这些是简短的例子。在T-SQL中创建复杂数据透视表

我的表/视图具有以下字段

Table/View 
    ReportID, 
    UnitName, 
    UnitID, 
    CaseDefinitionID, 
    CaseDefinition, 
    DateOfDelivery, 
    YEAR(DateOfDelivery) AS [Year], 
    MONTH(DateOfDelivery) AS [Month], 
    DATENAME(m,DateOfDelivery) AS [Month name] 

和我的目标报告:

Unit | Case type 1| Case type 2| Case total| 
Unit A |   36|    40|   76| 

    2013|   20|    18|   38| 
    Jan|   10| 
    Feb|   10| 

    2014|   16| 
    Mar|    8| 
    Dec|    8| 

Unit B |   12| 
    2013|   12| 
    Jan|    6| 
    May|    6| 

Grand total|   48| 

月份行可以是空的,空的内容是罚款。该示例报告不完整,以帮助澄清。

迄今取得的进展是以下查询:

SELECT * 
FROM 
(
    SELECT 
     PCT.[Year], 
     PCT.UnitName AS [Unit], 
     PCT.UnitID, 
     PCT.CaseDefinition AS [Case definition] 

    FROM 
     PivotBase AS PCT    
) AS P1 

PIVOT 
(
    COUNT(UnitID) 
    FOR [Case definition] IN ([Case type 1],[Case type 2]) 
) AS P2 

这将产生如下表

Year|Unit |Case type 1|Case type 2| 
2013|Unit A |  20 |   18| 
2014|Unit A |  16 |   22| 
2013|Unit B |  6 |   8| 
2014|Unit B |  6 |   8| 

没有必要对动态SQL

我读迄今已涵盖了许多选项但我仍然不知道下一步该去哪里。我如何制作所需的报告。

+0

我想你应该刚刚输出的标准化形式,依靠Excel进行转动到达那里。你是否有理由在SQL中执行此操作? – 2014-10-06 20:38:40

+0

@ZoffDino Excel不是一个可悲的选择;这是一个网站。我也可以用C#编写它,但又不是一个真正的选择。 – 2014-10-06 20:40:42

回答

2

您可以通过旋转上月份和年份,然后使用WITH ROLLUP

WITH data 
    AS (SELECT * 
     FROM (SELECT Dateadd(month, Datediff(month, 0, PCT.dateofdelivery), 0 
         ) 
         MonthYear, 
         PCT.unitid, 
         PCT.unitname 
         AS 
         [Unit], 
         PCT.casedefinition 
         AS 
           [Case definition] 
       FROM pivotbase AS PCT) AS P1 
       PIVOT (Count(unitid) 
         FOR [case definition] IN ([Case type 1], 
               [Case type 2])) AS p2), 
    rollup 
    AS (SELECT Month(monthyear)   Month, 
       unit      unitX, 
       Year(monthyear)   Year, 
       Sum([case type 1])   [case type 1], 
       Sum([case type 2])   [case type 2], 
       Grouping(unit)    GUnit, 
       Grouping(Month(monthyear)) gm, 
       Grouping(Year(monthyear)) gy 
     FROM data 
     GROUP BY unit, 
        Year(monthyear), 
        Month(monthyear) WITH rollup) 
SELECT COALESCE(Cast(month AS VARCHAR), Cast(year AS VARCHAR), unitx, 
     'Grand Total') 
     Unit, 
     [case type 1], 
     [case type 2] 
FROM rollup 
ORDER BY gunit, 
      unitx, 
      year, 
      gm DESC, 
      month 

SQLFiddle

2

这是可行的一些花哨汇总(SQL Fiddle

;WITH 
    CTE1 AS 
    (
     SELECT  UnitName, 
        [Year], 
        [Month], 
        CaseDefinition, 
        GROUPING_ID(UnitName,[Year],[Month],CaseDefinition) 
             AS GroupingID, 
        CASE GROUPING_ID(CaseDefinition,UnitName,[Year],[Month]) 
         WHEN 0 THEN UnitName + '-' + CAST(Year AS varchar(4)) + '-' + RIGHT('0' + CAST([Month] AS varchar(10)),2) 
         WHEN 1 THEN UnitName + '-' + CAST(Year AS varchar(4)) 
         WHEN 3 THEN UnitName 
         WHEN 7 THEN 'zzz' -- So that grand total appears at the bottom 
         ELSE NULL 
        END     AS GroupingLevel, 
        CASE GROUPING_ID(CaseDefinition,UnitName,[Year],[Month]) 
         WHEN 0 THEN ' ' + CASE [Month] 
               WHEN 1 THEN 'Jan' 
               WHEN 2 THEN 'Feb' 
               WHEN 3 THEN 'Mar' 
               WHEN 4 THEN 'Apr' 
               WHEN 5 THEN 'May' 
               WHEN 6 THEN 'Jun' 
               WHEN 7 THEN 'Jul' 
               WHEN 8 THEN 'Aug' 
               WHEN 9 THEN 'Sep' 
               WHEN 10 THEN 'Oct' 
               WHEN 11 THEN 'Nov' 
               WHEN 12 THEN 'Dec' 
              END 
         WHEN 1 THEN ' ' + CAST([Year] AS varchar(4)) 
         WHEN 3 THEN UnitName 
         WHEN 7 THEN 'Grand Total' 
        END     AS DisplayName, 
        COUNT(UnitID)  AS UnitCount 
     FROM  PivotBase 
     GROUP BY GROUPING SETS(
         (CaseDefinition), 
         (UnitName,CaseDefinition), 
         (UnitName,[Year],[CaseDefinition]), 
         (UnitName,[Year],[Month],CaseDefinition) 
        ) 
    ) 

SELECT  pvt.GroupingLevel, 
      pvt.DisplayName, 
      pvt.[Case Type 1], 
      pvt.[Case Type 2], 
      ISNULL(pvt.[Case Type 1],0) + ISNULL(pvt.[Case Type 2],0) AS [Case Total] 
FROM  CTE1 
PIVOT  (
       SUM(UnitCount) FOR CaseDefinition IN ([Case Type 1],[Case Type 2]) 
      ) pvt 
ORDER BY GroupingLevel 

说明:

  1. GROUPING SET((set1), (set2), (set3))定义卷起水平。你会得到的UnitID计数为每一个独特的组合set1,然后set2,然后set3

  2. GROUPING_ID是最不起眼的功能在这里。把它看成是一个掩码。如果列被聚合,则其位值设置为1.例如:。如果所有4个未汇总,则位掩码为0000 = 0。如果将field0汇总在一起,则返回值为0001 = 1,依此类推。

您可以用SELECT * FROM CTE1替换最后一个SELECT来查看查询的内部工作。

+0

我在旋转之后使用了Rollup,而不是之前使用了GROUPING_ID – 2014-10-06 22:37:47