6

我有一组输出数据透视表的查询。是否可以获得数据透视表的行和/或列小计?

我选择的桌子看起来像这样

    Site     FormID   Present
    Site 1   Form A      Yes
    Site 1   Form B      Yes
    Site 1   Form D      Yes

ETC...

我的数据透视表查询是这个

   SELECT *
   FROM (SELECT Site, COUNT(FormID) AS NumberOfForms,FormID
         FROM @CRFCount WHERE Present='Yes'
         GROUP BY Site, FormID) d
   PIVOT
   (SUM(NumberOfForms)
   FOR [Site] IN ([Site 1], [Site 2], [Site 3])
   )  AS p;

但我真的希望它导致这个(当然这对我来说并不完全)

    FormID  Site 1  Site 2  Site 3  Total
    Form A      8      8      15    31
    Form B     14      4    NULL    18
    Form C     14   NULL    NULL    14
    Form D     15      3      16    34
    Form E     12      4    NULL    16
    Form F     14      5       5    24
    Form G     14      8       6    28
    Form H     22     10      15    47
    Form I     15     10      16    41
    Form J     15      5      16    36
    Total     143     57      89   289

感谢你的协助 !

-大学教师

4

3 回答 3

7
;WITH C as
(
  SELECT FormID,
         [Site 1],
         [Site 2],
         [Site 3],
         (SELECT SUM(S)
          FROM (VALUES([Site 1]),
                      ([Site 2]),
                      ([Site 3])) AS T(S)) as Total
   FROM (SELECT Site, COUNT(FormID) AS NumberOfForms,FormID
         FROM @CRFCount WHERE Present='Yes'
         GROUP BY Site, FormID) d
   PIVOT
   (SUM(NumberOfForms)
   FOR [Site] IN ([Site 1], [Site 2], [Site 3])
   )  AS p
)
SELECT *
FROM
  (
    SELECT FormID,
           [Site 1],
           [Site 2],
           [Site 3],
           Total
    FROM C
    UNION ALL
    SELECT 'Total',
           SUM([Site 1]),
           SUM([Site 2]),
           SUM([Site 3]),
           SUM(Total)
    FROM C
  ) AS T
ORDER BY CASE WHEN FormID = 'Total' THEN 1 END

注意:如果您使用的是 SQL Server 2005,则需要更改:

 (SELECT SUM(S)
  FROM (VALUES([Site 1]),
              ([Site 2]),
              ([Site 3])) AS T(S)) as Total

 (SELECT SUM(S)
  FROM (SELECT [Site 1] UNION ALL
        SELECT [Site 2] UNION ALL
        SELECT [Site 3]) AS T(S)) as Total

尝试SE 数据

于 2011-10-28T06:43:11.113 回答
2

试试这个(未测试):

SELECT *
FROM
(
    SELECT
        Site = case when grouping(Site)=1 then 'All' else Site end,
        FormID = case when grouping(FormID)=1 then 'All' else cast(FormID as varchar(100)) end,
        measure = count(NumberOfForms)
    FROM @CRFCount 
       -- chose below
       GROUP BY Site, FormID with cube --(ms sql 2005)
       --group by grouping sets(Site, FormID, (Site, FormID), ()) --(ms sql 2008)
) AS BOM
PIVOT  (max(measure) FOR [Site] IN ([Site 1], [Site 2], [Site 3], [All]))
as pv
于 2011-10-28T09:49:00.043 回答
0

样品表

SELECT * INTO #TEMP 
FROM
(
    SELECT 'Site 1' [Site],   'Form A' [FormID],      'Yes' Present
    UNION ALL
    SELECT 'Site 1',   'Form B',      'Yes'
    UNION ALL
    SELECT 'Site 1',   'Form C',      'Yes'
    UNION ALL
    SELECT 'Site 1',   'Form B',      'NO'
    UNION ALL
    SELECT 'Site 1',   'Form C',      'NO'
    UNION ALL
    SELECT 'Site 2',   'Form A',      'Yes'
    UNION ALL
    SELECT 'Site 2',   'Form A',      'Yes'
    UNION ALL
    SELECT 'Site 2',   'Form B',      'Yes'
    UNION ALL
    SELECT 'Site 2',   'Form B',      'NO'
    UNION ALL
    SELECT 'Site 2',   'Form C',      'Yes'
    UNION ALL
    SELECT 'Site 3',   'Form B',      'Yes'
    UNION ALL
    SELECT 'Site 3',   'Form A',      'Yes'
    UNION ALL
    SELECT 'Site 3',   'Form C',      'Yes'
    UNION ALL
    SELECT 'Site 3',   'Form A',      'Yes'
)TAB

1. 行列合计

-- Get the columns for dynamic pivot
DECLARE @cols NVARCHAR (MAX)

SELECT @cols = COALESCE (@cols + ',[' + [Site] + ']', '[' + [Site] + ']')
               FROM (SELECT DISTINCT [Site] FROM  #TEMP WHERE Present='YES') PV 
               ORDER BY [Site] 
-- Since we need Total in last column, we append it at last
SELECT @cols += ',[Total]'

您可以使用CUBE在透视时获取行和列总计。更多关于CUBE 这里

DECLARE @query NVARCHAR(MAX)
SET @query = 'SELECT FORMID,' + @cols + ' FROM 
             (
                 SELECT 
                 ISNULL([SITE],''Total'')[SITE], 
                 SUM(CNT)CNT , 
                 ISNULL(FORMID,''Total'')FORMID              
                 FROM 
                 (
                    SELECT DISTINCT [SITE],FORMID,
                    COUNT(FORMID) OVER(PARTITION BY [SITE],FORMID) CNT
                    FROM #TEMP
                    WHERE PRESENT=''YES''
                 )TAB
                 GROUP BY [SITE],FORMID
                 WITH CUBE
             ) x
             PIVOT 
             (
                 MIN(CNT)
                 FOR [SITE] IN (' + @cols + ')
            ) p
            ORDER BY CASE WHEN (FORMID=''Total'') THEN 1 ELSE 0 END,FORMID' 

EXEC SP_EXECUTESQL @query

2. 仅行总计

您可以使用ROLLUP来获取行总数。

-- Get the columns for dynamic pivot
DECLARE @cols NVARCHAR (MAX)

SELECT @cols = COALESCE (@cols + ',[' + [Site] + ']', '[' + [Site] + ']')
               FROM (SELECT DISTINCT [Site] FROM  #TEMP WHERE Present='YES') PV 
               ORDER BY [Site] 



DECLARE @query NVARCHAR(MAX)
SET @query = 'SELECT FORMID,' + @cols + ' FROM 
             (
                 SELECT 
                 ISNULL([SITE],''Total'')[SITE], 
                 SUM(CNT)CNT , 
                 ISNULL(FORMID,''Total'')FORMID              
                 FROM 
                 (
                    SELECT DISTINCT [SITE],FORMID,
                    COUNT(FORMID) OVER(PARTITION BY [SITE],FORMID) CNT
                    FROM #TEMP
                    WHERE PRESENT=''YES''
                 )TAB
                 GROUP BY [SITE],FORMID
                 WITH ROLLUP
             ) x
             PIVOT 
             (
                 MIN(CNT)
                 FOR [SITE] IN (' + @cols + ')
            ) p
            ORDER BY CASE WHEN (FORMID=''Total'') THEN 1 ELSE 0 END,FORMID' 

EXEC SP_EXECUTESQL @query

3. 仅列总计

更改GROUP BY [SITE],FORMIDGROUP BY FORMID,[SITE]

-- Get the columns for dynamic pivot
DECLARE @cols NVARCHAR (MAX)

SELECT @cols = COALESCE (@cols + ',[' + [Site] + ']', '[' + [Site] + ']')
               FROM (SELECT DISTINCT [Site] FROM  #TEMP WHERE Present='YES') PV 
               ORDER BY [Site] 

 --Since we need Total in last column, we append it at last
SELECT @cols += ',[Total]'


DECLARE @query NVARCHAR(MAX)
SET @query = 'SELECT FORMID,' + @cols + ' FROM 
             (
                 SELECT 
                 ISNULL([SITE],''Total'')[SITE], 
                 SUM(CNT)CNT , 
                 ISNULL(FORMID,''Total'')FORMID              
                 FROM 
                 (
                    SELECT DISTINCT [SITE],FORMID,
                    COUNT(FORMID) OVER(PARTITION BY [SITE],FORMID) CNT
                    FROM #TEMP
                    WHERE PRESENT=''YES''
                 )TAB
                 GROUP BY FORMID,[SITE]
                 WITH ROLLUP
             ) x
             PIVOT 
             (
                 MIN(CNT)
                 FOR [SITE] IN (' + @cols + ')
            ) p
            WHERE FORMID <> ''Total''
            ORDER BY FORMID' 

EXEC SP_EXECUTESQL @query

现在,如果你想用零替换 null,你可以在动态透视之前使用下面的代码。

DECLARE @NulltoZeroCols NVARCHAR (MAX)

SELECT @NullToZeroCols = SUBSTRING((SELECT ',ISNULL(['+[Site]+'],0) AS ['+[Site]+']' 
FROM (SELECT DISTINCT [Site] FROM #TEMP)TAB  
ORDER BY [Site] FOR XML PATH('')),2,8000) 

SELECT @NullToZeroCols += ',ISNULL([Total],0) AS [Total]'

并且在动态枢轴的最外查询中,将@cols变量替换为@NullToZeroCols

于 2015-02-16T14:57:27.470 回答