具有多个“选择”列的动态轴中的行和列总计

时间:2017-03-21 07:36:15

标签: sql sql-server sql-server-2008

在SQL Server 2008中,我有一个包含4列的表tblStock

PartCode (NVARCHAR (50)) 
Role (NVarchar(10)) 
StockQty (INT) 
Location (NVARCHAR(50))

下面的一些示例数据:

Data From Temporary Table

我已编写此代码以获得以下输出:

IF OBJECT_ID('tempdb..#tblData') IS NOT NULL 
    DROP TABLE #tblData 

SELECT * 
INTO #tblData 
FROM 
    (SELECT 'A' PartCode, 'Manager' As [Role],  10 StockQty, 'in-A' Location
     UNION ALL
     SELECT 'B', 'Director' As [Role], 22, 'in-A'
     UNION ALL
     SELECT 'A', 'Director' As [Role], 1, 'in-B'
     UNION ALL
     SELECT 'C', 'Director' As [Role], 20, 'in-A'
     UNION ALL
     SELECT 'D', 'Director' As [Role], 39, 'in-F'
     UNION ALL
     SELECT 'E', 'Director' As [Role],  3,   'in-D'
     UNION ALL
     SELECT 'F', 'Director' As [Role],  7,   'in-A'
     UNION ALL
     SELECT 'A', 'Director' As [Role],  9,   'in-C'
     UNION ALL
     SELECT 'D', 'Director' As [Role],  2,   'in-A'
     UNION ALL
     SELECT 'F', 'Director' As [Role],  54,  'in-E') TAB

SELECT * 
FROM #tblData

DECLARE @cols NVARCHAR (MAX)

SELECT @cols = COALESCE (@cols + ',[' + Location + ']', '[' + Location + ']')
               FROM (SELECT DISTINCT Location FROM #tblData) PV 
               ORDER BY Location 

SELECT @cols += ',[Total]' 

DECLARE @NulltoZeroCols NVARCHAR (MAX) 
SELECT @NullToZeroCols = SUBSTRING((SELECT ',ISNULL(['+Location+'],0) AS ['+Location+']' 
FROM (SELECT DISTINCT Location FROM #tblData)TAB  
ORDER BY Location FOR XML PATH('')),2,8000) 

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

DECLARE @query NVARCHAR(MAX)
SET @query = 'SELECT PartCode, Role, ' + @NulltoZeroCols + ' FROM 
             (
                 SELECT 
                 ISNULL(CAST(PartCode AS VARCHAR(30)),''Total'')PartCode, 
                 Role,
                 SUM(StockQty)StockQty , 
                 ISNULL(Location,''Total'')Location              
                 FROM #tblData 
                 GROUP BY Location,PartCode,Role 
                 WITH CUBE
             ) x
             PIVOT 
             (
                 MIN(StockQty)
                 FOR Location IN (' + @cols + ')
            ) p
            ORDER BY CASE WHEN (PartCode=''Total'') THEN 1 ELSE 0 END,PartCode' 

EXEC SP_EXECUTESQL @query 

以上查询的结果是:

Output With Errors

我想得到这样的结果:

Correct Image

请分享您的想法 - 谢谢!

3 个答案:

答案 0 :(得分:1)

不是MIN,请使用SUM。此外,您不应选择“角色”列。

试试这个;

DECLARE @cols NVARCHAR (MAX)

SELECT @cols = COALESCE (@cols + ',[' + Location + ']', '[' + Location + ']')
               FROM (SELECT DISTINCT Location FROM #tblData) PV 
               ORDER BY Location 

SELECT @cols += ',[Total]' 

DECLARE @NulltoZeroCols NVARCHAR (MAX) 
SELECT @NullToZeroCols = SUBSTRING((SELECT ',ISNULL(['+Location+'],0) AS ['+Location+']' 
FROM (SELECT DISTINCT Location FROM #tblData)TAB  
ORDER BY Location FOR XML PATH('')),2,8000) 

DECLARE @SumCols NVARCHAR (MAX) 
SELECT @SumCols = SUBSTRING((SELECT '+(ISNULL(['+Location+'],0))' 
FROM (SELECT DISTINCT Location FROM #tblData)TAB  
ORDER BY Location FOR XML PATH('')),2,8000) 
PRINT @SumCols

SET @SumCols += ') AS [Total]'

DECLARE @query NVARCHAR(MAX)
SET @query = 'SELECT PartCode, (SELECT TOP 1 Role FROM #tblData WHERE PartCode=p.PartCode) Role, ' + @NulltoZeroCols +', ('+ @SumCols+' FROM 
             (
                 SELECT 
                 ISNULL(CAST(PartCode AS VARCHAR(30)),''Total'')PartCode, 

                 SUM(StockQty)StockQty , 
                 ISNULL(Location,''Total'')Location              
                 FROM #tblData 
                 GROUP BY Location,PartCode 
                 WITH CUBE
             ) x
             PIVOT 
             (
                 MIN(StockQty)
                 FOR Location IN (' + @cols + ')
            ) p
            ORDER BY CASE WHEN (PartCode=''Total'') THEN 1 ELSE 0 END,PartCode' 
PRINT @query
EXEC SP_EXECUTESQL @query 

答案 1 :(得分:1)

更新的部分将是,

SET @query = 'SELECT PartCode, Role, ' + @NulltoZeroCols + ' FROM 
             (
                SELECT PartCode, Role, StockQty, Location
                FROM #tblData
                UNION ALL

                SELECT PartCode, Role, SUM(StockQty), ''Total'' as Location
                FROM #tblData
                GROUP BY PartCode, Role            

                UNION ALL

                  SELECT 
                 ''Total'' PartCode, 
                 ''Total'' Role, 
                 SUM(StockQty)StockQty , 
                 ISNULL(Location,''Total'')Location              
                 FROM #tblData
                 GROUP BY Location   
                 WITH cube
             ) x
             PIVOT 
             (
                 MIN(StockQty)
                 FOR Location IN (' + @cols + ')
            ) p
            ORDER BY CASE WHEN (PartCode=''Total'') THEN 1 ELSE 0 END,PartCode'

答案 2 :(得分:0)

DECLARE @query NVARCHAR(MAX) SET @query = 'SELECT p.PartCode, (SELECT TOP 1 Role FROM #tblData t3 WHERE t3.PartCode = p.PartCode and t3.Role = t2.Role ) Role, ' + @NullToZeroCols +', ('+ @SumCols+' FROM ( SELECT ISNULL(CAST(t1.PartCode AS VARCHAR(30)),''Total'')PartCode, -- Role, SUM(StockQty)StockQty , ISNULL(Location,''Total'')Location
FROM #tblData t1 GROUP BY Location,t1.PartCode WITH CUBE ) x PIVOT ( MIN(StockQty) FOR Location IN (' + @cols + ') ) p left JOIN #tblData t2 on t2.PartCode = p.PartCode GROUP BY t2.Role,p.PartCode, ' + @cols +' ORDER BY CASE WHEN (p.PartCode=''Total'') THEN 1 ELSE 0 END,p.PartCode'
PRINT @query EXEC (@query)