Dynamic Pivot/Unpivot

  • Hello, 
    I have a table like below, where headers of columns and rows are dynamic (this is a result of query)

    GroupSizePriceOthers
    Summary43349
    Main35295
    Various211
    Special523
    Turbo12-1

    Is there a way in SQL to "rotate' that table on below way:

    SummaryMainVariousSpecialTurbo
    Size4335251
    Price2429122
    Others9513-1

    I was able to use CURSORS to achieve the results, but I am wondering if there is maybe easier one, eg.: using PIVOT nad UNPIVOT.
    Thank you!

  • psobanski - Tuesday, November 7, 2017 3:12 AM

    Hello, 
    I have a table like below, where headers of columns and rows are dynamic (this is a result of query)

    GroupSizePriceOthers
    Summary43349
    Main35295
    Various211
    Special523
    Turbo12-1

    Is there a way in SQL to "rotate' that table on below way:

    SummaryMainVariousSpecialTurbo
    Size4335251
    Price2429122
    Others9513-1

    I was able to use CURSORS to achieve the results, but I am wondering if there is maybe easier one, eg.: using PIVOT nad UNPIVOT.
    Thank you!

    Can you post your data in a consumable format? That means DDL and insert statements. If you need help on how to do it, check the articles on my signature. To achieve your goal, you need to unpivot and then pivot the data, but I won't suggest using those operators. Instead, I suggest using what is explained in the following articles:
    An Alternative (Better?) Method to UNPIVOT (SQL Spackle) - SQLServerCentral
    Cross Tabs and Pivots, Part 1 – Converting Rows to Columns - SQLServerCentral
    Cross Tabs and Pivots, Part 2 - Dynamic Cross Tabs - SQLServerCentral

    If you post the consumable sample data, I can  give an example on how to apply the techniques from the articles.

    Luis C.
    General Disclaimer:
    Are you seriously taking the advice and code from someone from the internet without testing it? Do you at least understand it? Or can it easily kill your server?

    How to post data/code on a forum to get the best help: Option 1 / Option 2
  • Dear Luis,
    Thank you for your response. One thing to be clarified. The list of columns in input table is known (not dynamic as I mentioned before). The values in column [Group] is dynamic and its fields should be the columns of "rotated table"
    Here is the code to generate the input table:
    create table #SummaryTable
    (
        [Group] varchar (48),
        Size float,
        Price float,
        Others float
    )

    insert into #SummaryTable ([Group], Size, Price, Others) values
    ('Summary', 43, 34, 9),
    ('Main', 35, 29, 5),
    ('Various', 2, 1, 1),
    ('Special', 5, 2, 3),
    ('Turbo', 1, 2, -1)

    select * from #SummaryTable
    drop table #SummaryTable

  • psobanski - Wednesday, November 8, 2017 3:03 AM

    Dear Luis,
    Thank you for your response. One thing to be clarified. The list of columns in input table is known (not dynamic as I mentioned before). The values in column [Group] is dynamic and its fields should be the columns of "rotated table"
    Here is the code to generate the input table:
    create table #SummaryTable
    (
        [Group] varchar (48),
        Size float,
        Price float,
        Others float
    )

    insert into #SummaryTable ([Group], Size, Price, Others) values
    ('Summary', 43, 34, 9),
    ('Main', 35, 29, 5),
    ('Various', 2, 1, 1),
    ('Special', 5, 2, 3),
    ('Turbo', 1, 2, -1)

    select * from #SummaryTable
    drop table #SummaryTable

    I think this will do what you need:

    DECLARE @SQL VARCHAR(MAX);

    SELECT
      @SQL
      = 'WITH unpvt AS (SELECT s.[Group], x.col, x.val FROM #SummaryTable s CROSS APPLY (VALUES (''Size'', Size), (''Price'', Price), (''Others'', Others)) x (col, val)) '
      + 'SELECT col AS NewGroup '
      +
    (
      SELECT
       ', MAX (CASE WHEN [Group] = ' + QUOTENAME([Group], '''') + ' THEN val ELSE NULL END) AS ' + QUOTENAME([Group])
      FROM #SummaryTable
      FOR XML PATH('')
    ).value('.', 'varchar(max)')   + ' FROM unpvt GROUP BY unpvt.col ORDER BY NewGroup DESC;';
    --SELECT @SQL; -- to test the query
    EXEC (@SQL);

    Thomas Rushton
    blog: https://thelonedba.wordpress.com

  • Some small improvements to Thomas' code. Even with dynamic code, I like to keep it with a good format to ease the debugging.
    I'm also using sp_executesql which would allow to use parameters in case they're needed.

    DECLARE @SQL NVARCHAR(MAX);

    SELECT @SQL = N'WITH unpvt AS (' + CHAR(13)
            + CHAR(9) + N'SELECT s.[Group]' + CHAR(13)
            + CHAR(9) + CHAR(9) + N',x.col' + CHAR(13)
            + CHAR(9) + CHAR(9) + N',x.val ' + CHAR(13)
            + CHAR(9) + N'FROM #SummaryTable s' + CHAR(13)
            + CHAR(9) + N'CROSS APPLY (VALUES (''Size'', Size), (''Price'', Price), (''Others'', Others)) x (col, val)' + CHAR(13)
            + N') ' + CHAR(13)
            + N'SELECT col AS NewGroup ' + CHAR(13)
            + (
               SELECT
               CHAR(9) + ', MAX (CASE WHEN [Group] = ' + QUOTENAME([Group], '''') + ' THEN val ELSE NULL END) AS ' + QUOTENAME([Group]) + CHAR(13)
               FROM #SummaryTable
               FOR XML PATH(''), TYPE
              ).value('./text()[1]', 'Nvarchar(max)')
            + N' FROM unpvt ' + CHAR(13)
            + N'GROUP BY unpvt.col ' + CHAR(13)
            + N'ORDER BY NewGroup DESC;';

      

    PRINT @SQL; -- to test the query
    EXEC sp_executesql @SQL;

    Luis C.
    General Disclaimer:
    Are you seriously taking the advice and code from someone from the internet without testing it? Do you at least understand it? Or can it easily kill your server?

    How to post data/code on a forum to get the best help: Option 1 / Option 2
  • ThomasRushton - Wednesday, November 8, 2017 4:46 AM

    psobanski - Wednesday, November 8, 2017 3:03 AM

    Thank you!

  • Luis Cazares - Wednesday, November 8, 2017 7:47 AM

    Thank you!

  • psobanski - Wednesday, November 8, 2017 10:02 AM

    Luis Cazares - Wednesday, November 8, 2017 7:47 AM

    Thank you!

    You're welcome. Now the important question is: Do you understand how this works?
    Remember that you'll be the one in charge of supporting this solution.

    Luis C.
    General Disclaimer:
    Are you seriously taking the advice and code from someone from the internet without testing it? Do you at least understand it? Or can it easily kill your server?

    How to post data/code on a forum to get the best help: Option 1 / Option 2

Viewing 8 posts - 1 through 7 (of 7 total)

You must be logged in to reply to this topic. Login to reply