2017-04-19 115 views
1

在SQL Server 2008中,我有一个表tblStock 3列:行和列的平均动态枢纽

PartCode (NVARCHAR (50)) 
StockQty (INT) 
Location (NVARCHAR(50)) 

下面一些示例数据:

enter image description here

我想要得到的以下输出,

enter image description here

我写了下面的查询来获取上面的输出,没有被正确返回Avg值:

IF OBJECT_ID('tempdb..#tblStock') IS NOT NULL /*Then it exists*/ 
    DROP TABLE #tblStock 

SELECT * 
INTO #tblStock 
FROM 
    (SELECT 'A' PartCode, 10 StockQty, 'WHs-A' Location 
    UNION ALL 
    SELECT 'B', 22, 'WHs-A' 
    UNION ALL 
    SELECT 'A', 1, 'WHs-B' 
    UNION ALL 
    SELECT 'C', 20, 'WHs-A' 
    UNION ALL 
    SELECT 'D', 39, 'WHs-F' 
    UNION ALL 
    SELECT 'E', 3, 'WHs-D' 
    UNION ALL 
    SELECT 'F', 7, 'WHs-A' 
    UNION ALL 
    SELECT 'A', 9, 'WHs-C' 
    UNION ALL 
    SELECT 'D', 2, 'WHs-A' 
    UNION ALL 
    SELECT 'F', 54, 'WHs-E') TAB 

SELECT * FROM #tblStock 

DECLARE @cols NVARCHAR (MAX) 
SELECT @cols = COALESCE (@cols + ',[' + Location + ']', '[' + Location + ']') 
       FROM (SELECT DISTINCT Location FROM #tblStock) PV 
       ORDER BY Location 
-- Since we need Total in last column, we append it at last 
SELECT @cols += ',[AVG]' 

-- Variable to replace NULL with zero 
DECLARE @NulltoZeroCols NVARCHAR (MAX) 
SELECT @NullToZeroCols = SUBSTRING((SELECT ',ISNULL(['+Location+'],0) AS ['+Location+']' 
FROM (SELECT DISTINCT Location FROM #tblStock)TAB 
ORDER BY Location FOR XML PATH('')),2,8000) 
SELECT @NullToZeroCols += ',ISNULL([AVG],0) AS [AVG]' 


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

EXEC SP_EXECUTESQL @query 

任何人都可以知道这个问题该如何解决?

回答

2

我用你的SET查询来获得你想要的结果。
我认为你需要添加RIGHT JOIN来列出每个PartCode和Location(否则AVG函数无法正确计数项目数)。我也将ISNULL添加到AVG(StockQty)。此外,您应该将数值平均值转换为数值。

SET @query = 'SELECT PartCode,' + @NulltoZeroCols + ' FROM 
      (SELECT      
       ISNULL(CAST(X.PC AS VARCHAR(30)),''AVG'') PartCode, 
       AVG(CAST(ISNULL(StockQty,0) AS NUMERIC(10,2))) StockQty,     
       ISNULL(Y.LC,''AVG'') Location    
       FROM #tblStock 
       RIGHT JOIN (SELECT DISTINCT PartCode AS PC FROM #tblStock) X 
          CROSS JOIN (SELECT DISTINCT Location AS LC FROM #tblStock) Y 
        ON Y.LC = #tblStock.LOCATION AND X.PC=#tblStock.PARTCODE 
       GROUP BY Y.LC, X.PC 
       WITH CUBE     
      ) x 
      PIVOT 
      (
       AVG(StockQty) 
       FOR Location IN (' + @cols + ') 
      ) p 
      ORDER BY CASE WHEN (PartCode=''AVG'') THEN 1 ELSE 0 END,PartCode' 

输出:

PartCode      WHs-A         WHs-B         WHs-C         WHs-D         WHs-E         WHs-F         AVG 
------------------------------ --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- --------------------------------------- 
A        10.000000        1.000000        9.000000        0.000000        0.000000        0.000000        3.333333 
B        22.000000        0.000000        0.000000        0.000000        0.000000        0.000000        3.666666 
C        20.000000        0.000000        0.000000        0.000000        0.000000        0.000000        3.333333 
D        2.000000        0.000000        0.000000        0.000000        0.000000        39.000000        6.833333 
E        0.000000        0.000000        0.000000        3.000000        0.000000        0.000000        0.500000 
F        7.000000        0.000000        0.000000        0.000000        54.000000        0.000000        10.166666 
AVG       10.166666        0.166666        1.500000        0.500000        9.000000        6.500000        4.638888