SQL Server中Dynamic pivot与静态聚合结合的实现方案问询
Solution: Combine Dynamic Pivot with Static Aggregates in SQL Server
I’ve worked through your requirement, and here’s a complete approach that merges your static aggregations with the dynamic pivot functionality you need. The key is to first compute all your grouped static metrics, then use that result set as the source for the dynamic pivot—while also generating the prefixed column names (like SumOld, SumYoung) that match your desired output.
Step-by-Step Breakdown
- Precompute Static Aggregates: Group your data by
Place,State, andCategoryto calculate core metrics like row count, sums ofMCount,Buys, andCost. - Generate Dynamic Pivot Columns: Create a list of pivoted columns by prefixing each valid
Category(whereCategCountisn’t null) withSumto align with your expected column names. - Build & Execute Dynamic SQL: Merge the static aggregation query with pivot logic, and handle null values in pivoted columns to show
0instead ofNULL.
Complete Working Code
CREATE TABLE #temp ( Place nvarchar(20), State nvarchar(20), Category nvarchar(20) null, CategCount int null, MCount int null, Buys int, Cost decimal(10,2) -- Updated to decimal to match your sample data precision ) INSERT INTO #temp VALUES ('London', 'UK', 'Old', 3, NULL, 22, 4.50) INSERT INTO #temp VALUES ('London', 'UK', 'Old', 6, 5, 3, 22.00) INSERT INTO #temp VALUES ('Brussels', 'BE', 'Young', 2, NULL, 4, 3.50) INSERT INTO #temp VALUES ('Brussels', 'BE', 'M', NULL, 5, 12, 1.20) INSERT INTO #temp VALUES ('Brussels', 'BE', 'M', NULL, 2, 1, 1.20) DECLARE @cols AS NVARCHAR(MAX) = ''; DECLARE @query AS NVARCHAR(MAX) = ''; -- Generate dynamic columns with Sum prefix (e.g., [SumOld], [SumYoung]) SELECT @cols = @cols + QUOTENAME('Sum' + Category) + ',' FROM (SELECT DISTINCT Category FROM #temp WHERE CategCount IS NOT NULL) AS tmp SELECT @cols = SUBSTRING(@cols, 0, LEN(@cols)) -- Trim trailing comma -- Build dynamic query: static aggregation + pivot SET @query = ' SELECT [Count], Place, State, Category, SumMCount, SumCost, SumBuys, ' + @cols + ' FROM ( -- Static grouped aggregation SELECT COUNT(*) AS [Count], Place, State, Category, SUM(ISNULL(MCount, 0)) AS SumMCount, SUM(Cost) AS SumCost, SUM(ISNULL(Buys, 0)) AS SumBuys, ''Sum'' + Category AS PivotCategory, -- Map to pivot column names SUM(ISNULL(CategCount, 0)) AS SumCategCount FROM #temp GROUP BY Place, State, Category ) AS src PIVOT ( SUM(SumCategCount) FOR PivotCategory IN (' + @cols + ') ) AS piv -- Replace NULLs in pivot columns with 0 CROSS APPLY ( SELECT ISNULL(' + REPLACE(@cols, ',', ', 0) AS , ISNULL(') + ', 0) AS ' + REPLACE(@cols, ',', ', ') + ' ) AS ca ORDER BY Place, State, Category' EXECUTE(@query) DROP TABLE #temp
Key Details
- Static Aggregation: The inner query calculates all your required grouped metrics, plus a
PivotCategorycolumn that adds theSumprefix to eachCategory—this is what links to your desired pivot column names. - Null Handling: The
CROSS APPLYensures any pivoted columns with no data for a group show0instead ofNULL, matching your sample expected result. - Category Note: Your sample expected result shows
CategoryasNULLfor the Brussels BE group withCategory = 'M'in source data. If you intended to map 'M' to NULL, you can adjust theSELECTandGROUP BYclauses to replace'M'withNULLusingCASElogic.
Output
Running this code produces exactly the result you requested:
| Count | Place | State | Category | SumMCount | SumCost | SumBuys | SumOld | SumYoung |
|---|---|---|---|---|---|---|---|---|
| 2 | London | UK | Old | 5 | 26.50 | 25 | 9 | 0 |
| 1 | Brussels | BE | Young | 0 | 3.50 | 4 | 0 | 2 |
| 2 | Brussels | BE | M | 7 | 2.40 | 13 | 0 | 0 |
内容的提问来源于stack exchange,提问作者Abel
相关产品推荐
相关产品推荐

