您可以对数据透视表中的行和/或列进行小计吗?

发布于 2024-12-12 05:52:30 字数 1074 浏览 0 评论 0原文

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

我从中选择的表看起来像这样

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

等...

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

   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

感谢您的帮助!

-大学教师

I have a set of queries that outputs a pivot table. Is it possible to obtain row and/or column subtotals for a pivot table ?

My table I am selecting from looks like this

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

etc...

My pivot table query is this

   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;

But I really want it to result in this (which of course it does not total for me)

    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

Thanks for your assistance !

-Don

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

握住我的手 2024-12-19 05:52:30
;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 数据

;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

Note: If you are using SQL Server 2005 you need to change this:

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

to

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

Try on SE Data

残疾 2024-12-19 05:52:30

试试这个(未测试):

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

Try this (not tested):

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
莫相离 2024-12-19 05:52:30

示例表

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],FORMID 更改为 GROUP 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

SAMPLE TABLE

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. Row and Column Total

-- 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]'

You can use CUBE to get the row and column total on pivoting. More about CUBE here.

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. Row Total only

You can use ROLLUP to get the row total.

-- 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. Column Total only

Change GROUP BY [SITE],FORMID to GROUP 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

Now, if you want to replace null with zero, you can use the below code before dynamic pivot.

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]'

And in the out most query of dynamic pivot, replace @cols variable with @NullToZeroCols

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文