样品表
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