Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Zeilen- und Spaltensumme im dynamischen Pivot

Beispieltabelle

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

Holen Sie sich die Spalten für dynamisches Pivotieren und ersetzen Sie NULL mit zero

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 += ',[Total]'


--Varible 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([Total],0) AS [Total]'

Sie können CUBE verwenden um Zeilen- und Spaltensummen zu finden und NULL zu ersetzen mit Total für die von CUBE generierten Zeilen .

DECLARE @query NVARCHAR(MAX)
SET @query = 'SELECT PartCode,' + @NulltoZeroCols + ' FROM 
             (
                 SELECT 
                 ISNULL(CAST(PartCode AS VARCHAR(30)),''Total'')PartCode, 
                 SUM(StockQty)StockQty , 
                 ISNULL(Location,''Total'')Location              
                 FROM #tblStock
                 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' 

EXEC SP_EXECUTESQL @query

ERGEBNIS

HINWEIS:Wenn Sie NULL möchten statt zero Verwenden Sie als Werte @cols statt @NulltoZeroCols im dynamischen Pivot-Code

BEARBEITEN :

1. Nur Zeilensumme anzeigen

  • Verwenden Sie nicht den Code SELECT @cols += ',[Total]' und SELECT @NullToZeroCols += ',ISNULL([Total],0) AS [Total]' .
  • Verwenden Sie ROLLUP statt CUBE .

2. Nur Spaltensumme anzeigen

  • Verwenden Sie den Code SELECT @cols += ',[Total]' und SELECT @NullToZeroCols += ',ISNULL([Total],0) AS [Total]' .
  • Verwenden Sie ROLLUP statt CUBE .
  • Ändern Sie GROUP BY Location,PartCode zu GROUP BY PartCode,Location .
  • Statt ORDER BY CASE WHEN (PartCode=''Total'') THEN 1 ELSE 0 END,PartCode , verwenden Sie WHERE PartCode<>''TOTAL'' ORDER BY PartCode .

UPDATE :Um PartName zu bringen für OP

Ich aktualisiere die folgende Abfrage, um PartName hinzuzufügen mit Ergebnis. Seit PartName fügt zusätzliche Ergebnisse mit CUBE hinzu und um Verwirrung in AND zu vermeiden oder OR Bedingungen, ist es besser, das Pivot-Ergebnis mit dem DISTINCT zu verbinden Werte in Ihrer Quelltabelle.

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

EXEC SP_EXECUTESQL @query