SQL Query with Dynamic Columns Using Pivot

后端 未结 3 2042
遥遥无期
遥遥无期 2021-01-25 08:40

I know this topic is everywhere but I couldn\'t get it to work properly. It\'s probably something very simple.

Here is a sample of the data after a basic query:

相关标签:
3条回答
  • 2021-01-25 09:19

    Using Dynamic Sql

    IF OBJECT_ID('tempdb..#TempData', 'U') IS NOT NULL 
    DROP TABLE #TempData;
    
    CREATE TABLE #TempData (
        [Site] CHAR(3) NOT NULL,
        Model VARCHAR(30) NOT NULL,
        SomeCount INT NOT NULL DEFAULT(0)
        );
    INSERT #TempData (Site, Model, SomeCount) VALUES
        ('AAA', 'ProLiant DL380 G7', 1), 
        ('AAA', 'OptiPlex 790', 500), 
        ('BBB', 'OptiPlex 780', 80),
        ('CCC', 'OptiPlex 790', 23);
    
    Declare @DynamicCol nvarchar(max),@DynamicColNull nvarchar(max)
            ,@Sql nvarchar(max)
    
    SELECT @DynamicColNull=STUFF((SELECT DISTINCT ', '+'ISNULL('+QUOTENAME(Model),','+'''0'''+') As '+QUOTENAME(Model)
                            FROM #TempData FOR XML PATH ('')),1,2,'')
    
    SELECT @DynamicCol=STUFF((SELECT DISTINCT ', '+QUOTENAME(Model) FROM #TempData FOR XML PATH ('')),1,2,'')
    
    SET @Sql='SELECT [Site], '+@DynamicColNull+' From
                (   
                SELECT * from #TempData
                )
                AS Src
                PIVOT
                (
                MAX(SomeCount) FOR [Model] IN ('+@DynamicCol+')
                )AS Pvt'
    PRINT @Sql
    EXEC(@Sql)
    

    Result

    Site    OptiPlex 780    OptiPlex 790    ProLiant DL380 G7
    AAA         0               500             1
    BBB         80              0               0
    CCC         0               23              0
    
    0 讨论(0)
  • 2021-01-25 09:22

    Give this a shot...

    IF OBJECT_ID('tempdb..#TestData', 'U') IS NOT NULL 
    DROP TABLE #TestData;
    
    CREATE TABLE #TestData (
        [Site] CHAR(3) NOT NULL,
        Model VARCHAR(30) NOT NULL,
        SomeCount INT NOT NULL DEFAULT(0)
        );
    INSERT #TestData (Site, Model, SomeCount) VALUES
        ('AAA', 'ProLiant DL380 G7', 1), 
        ('AAA', 'OptiPlex 790', 500), 
        ('BBB', 'OptiPlex 780', 80),
        ('CCC', 'OptiPlex 790', 23);
    
    --==========================================================
    
    DECLARE 
        @PivotColumns NVARCHAR(4000),
        @sql NVARCHAR(4000),
        @DeBug BIT = 0;
    
    SELECT 
        @PivotColumns = CONCAT(@PivotColumns, N',
        ', QUOTENAME(td.Model), N' = SUM(CASE WHEN td.Model = ', QUOTENAME(td.Model, ''''), N' THEN td.SomeCount END)') 
    FROM
        #TestData td
    GROUP BY
        td.Model
    -- ORDER BY ??? if you want the columns in a specific ordinal position.
    ;
    
    SET @sql = CONCAT(N'
    SELECT 
        td.[Site]',
        @PivotColumns, N'
    FROM
        #TestData td
    GROUP BY
        td.[Site];');
    
    IF @DeBug = 1
    BEGIN 
        PRINT (@sql);
    END;
    ELSE 
    BEGIN 
        EXEC sys.sp_executesql @sql;
    END;
    

    Results...

    Site OptiPlex 780 OptiPlex 790 ProLiant DL380 G7
    ---- ------------ ------------ -----------------
    AAA  NULL         500          1
    BBB  80           NULL         NULL
    CCC  NULL         23           NULL
    
    0 讨论(0)
  • 2021-01-25 09:28

    From your query

    PIVOT
    (
        max(Model)
        FOR Site in ' + @cols + ')
    ) AS piv
    

    you should use the column Count in MAX() function and Model in FOR...IN section. this is because your new values will be the Count and your new columns will be from the values in Model

    0 讨论(0)
提交回复
热议问题