Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Total des lignes et des colonnes dans le pivot dynamique

TABLEAU D'EXEMPLE

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

Obtenez les colonnes pour le pivotement dynamique et remplacez NULL avec 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]'

Vous pouvez utiliser CUBE pour trouver le total des lignes et des colonnes et remplacer NULL avec Total pour les lignes générées depuis CUBE .

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

RÉSULTAT

REMARQUE :Si vous voulez NULL au lieu de zero comme valeurs, utilisez @cols au lieu de @NulltoZeroCols en code pivot dynamique

MODIF :

1. Afficher uniquement le total de la ligne

  • N'utilisez pas le code SELECT @cols += ',[Total]' et SELECT @NullToZeroCols += ',ISNULL([Total],0) AS [Total]' .
  • Utilisez ROLLUP au lieu de CUBE .

2. Afficher uniquement le total de la colonne

  • Utilisez le code SELECT @cols += ',[Total]' et SELECT @NullToZeroCols += ',ISNULL([Total],0) AS [Total]' .
  • Utilisez ROLLUP au lieu de CUBE .
  • Modifier GROUP BY Location,PartCode à GROUP BY PartCode,Location .
  • Au lieu de ORDER BY CASE WHEN (PartCode=''Total'') THEN 1 ELSE 0 END,PartCode , utilisez WHERE PartCode<>''TOTAL'' ORDER BY PartCode .

MISE À JOUR :Pour apporter PartName pour OP

Je mets à jour la requête ci-dessous pour ajouter PartName avec résultat. Depuis PartName ajoutera des résultats supplémentaires avec CUBE et pour éviter toute confusion dans AND ou OR conditions, il vaut mieux joindre le résultat pivoté avec le DISTINCT valeurs dans votre table source.

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