How to pivot table?

Sh AS 41 Reputation points
2020-11-16T13:21:04.947+00:00

I have a table with following values.

Type New Closed Reopen
Claim 32 14 97
Line 14 37 7

How do I pivot the results in the following form?

Status Claim Line
New 32 14
Closed 14 37
Reopen 97 7

Thanks.

Transact-SQL
Transact-SQL
A Microsoft extension to the ANSI SQL language that includes procedural programming, local variables, and various support functions.
4,624 questions
0 comments No comments
{count} votes

Accepted answer
  1. Viorel 116.6K Reputation points
    2020-11-16T18:34:13.263+00:00

    In addition, try the next example:

    declare @table as table (Type varchar(10), New int, Closed int, Reopen int)
    
    insert @table values
    ( 'Claim', 32, 14, 97 ),
    ( 'Line ', 14, 37,  7 )
    
    select * from @table
    
    ---
    
    select [Status], [Claim], [Line]
    from @table
    unpivot
    (
        [val] for [Status] in( [New], [Closed], [Reopen] ) 
    ) as u
    pivot
    (
        sum(val) for [type] in( [Claim], [Line] ) 
    ) as p
    
    /*
    Status  Claim   Line
    Closed  14      37
    New     32      14
    Reopen  97       7
    */
    

    This also assumes that “Claim” and “Line” are the only (fixed) types. Otherwise a dynamic SQL can be considered.

    2 people found this answer helpful.

4 additional answers

Sort by: Most helpful
  1. Yitzhak Khabinsky 25,851 Reputation points
    2020-11-16T15:35:24.877+00:00

    You can try the following method via XQuery.

    SQL

    -- DDL and sample data population, start
    DECLARE @tbl TABLE (Type VARCHAR(20), New INT, Closed INT, Reopen INT);
    INSERT INTO @tbl (Type, New, Closed, Reopen) VALUES
    ('Claim', 32, 14, 97),
    ('Line', 14, 37, 7);
    -- DDL and sample data population, end
    
    SELECT * FROM @tbl;
    
    ;WITH rs AS
    (
        SELECT (
            SELECT * FROM @tbl
            FOR XML PATH('r'), TYPE, ROOT('root')
        ).query('<root>
        {
                for $y in (1,2,3)
                return <r status="{local-name((/root/r[1]/*[$y + 1])[1])}" 
                    claim="{/root/r[1]/*[$y + 1]}" 
                    line="{/root/r[2]/*[$y + 1]}"></r>
        }
        </root>') AS xmldata
    )
    SELECT c.value('@status', 'VARCHAR(20)') AS [status]
        , c.value('@claim', 'INT') AS claim
        , c.value('@line', 'INT') AS line
    FROM rs CROSS APPLY xmldata.nodes('/root/r') AS t(c);
    
    1 person found this answer helpful.
    0 comments No comments

  2. SQLZealots 276 Reputation points
    2020-11-16T17:00:57.6+00:00
    0 comments No comments

  3. Guoxiong 8,206 Reputation points
    2020-11-16T18:18:22.607+00:00

    If you want to use the PIVOT operator to achieve your target, try this:

    DECLARE @MyTable TABLE (
        [Type] varchar(20),
        [New] int,
        [Closed] int, 
        [Reopen] int
    );
    
    INSERT INTO @MyTable VALUES
    ('Claim', 32, 14, 97),
    ('Line', 14, 37, 7);
    
    
    ;WITH CTE_New AS (
        SELECT 'New' AS [Status], [Claim], [Line]
        FROM (
            SELECT [Type], [New] FROM @MyTable
        ) AS src
        PIVOT (
            SUM([New])
            FOR [Type] IN ([Claim], [Line])
        ) AS pvt
    ),
    CTE_Closed AS (
        SELECT 'Closed' AS [Status], [Claim], [Line]
        FROM (
            SELECT [Type], [Closed] FROM @MyTable
        ) AS src
        PIVOT (
            SUM([Closed])
            FOR [Type] IN ([Claim], [Line])
        ) AS pvt
    ),
    CTE_Reopen AS (
        SELECT 'Reopen' AS [Status], [Claim], [Line]
        FROM (
            SELECT [Type], [Reopen] FROM @MyTable
        ) AS src
        PIVOT (
            SUM([Reopen])
            FOR [Type] IN ([Claim], [Line])
        ) AS pvt
    )
    
    SELECT [Status], [Claim], [Line]
    FROM CTE_New
    UNION ALL
    SELECT [Status], [Claim], [Line]
    FROM CTE_Closed
    UNION ALL
    SELECT [Status], [Claim], [Line]
    FROM CTE_Reopen;
    

  4. Viorel 116.6K Reputation points
    2020-11-16T18:25:07.097+00:00

    Check this approach too:

    declare @table as table (Type varchar(10), New int, Closed int, Reopen int)
    
    insert @table values
    ( 'Claim', 32, 14, 97 ),
    ( 'Line ', 14, 37,  7 )
    
    select * from @table
    
    ---
    
    select [Status], [Claim], [Line]
    from (
        select [Type], 'New' as [Status], New as val from  @table
        union all
        select [Type], 'Closed', Closed from  @table
        union all
        select [Type], 'Reopen', Reopen from  @table
        ) as t
    pivot
    (
        sum(val) for [type] in( [Claim], [Line] ) 
    ) as p
    
    /*
    Status  Claim   Line
    Closed  14      37
    New     32      14
    Reopen  97       7
    */
    
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.