SQL Server : Columns to Rows

后端 未结 6 1142
孤城傲影
孤城傲影 2020-11-22 03:11

Looking for elegant (or any) solution to convert columns to rows.

Here is an example: I have a table with the following schema:

[ID] [EntityID] [Indi         


        
6条回答
  •  [愿得一人]
    2020-11-22 03:35

    well If you have 150 columns then I think that UNPIVOT is not an option. So you could use xml trick

    ;with CTE1 as (
        select ID, EntityID, (select t.* for xml raw('row'), type) as Data
        from temp1 as t
    ), CTE2 as (
        select
             C.id, C.EntityID,
             F.C.value('local-name(.)', 'nvarchar(128)') as IndicatorName,
             F.C.value('.', 'nvarchar(max)') as IndicatorValue
        from CTE1 as c
            outer apply c.Data.nodes('row/@*') as F(C)
    )
    select * from CTE2 where IndicatorName like 'Indicator%'
    

    sql fiddle demo

    You could also write dynamic SQL, but I like xml more - for dynamic SQL you have to have permissions to select data directly from table and that's not always an option.

    UPDATE
    As there a big flame in comments, I think I'll add some pros and cons of xml/dynamic SQL. I'll try to be as objective as I could and not mention elegantness and uglyness. If you got any other pros and cons, edit the answer or write in comments

    cons

    • it's not as fast as dynamic SQL, rough tests gave me that xml is about 2.5 times slower that dynamic (it was one query on ~250000 rows table, so this estimate is no way exact). You could compare it yourself if you want, here's sqlfiddle example, on 100000 rows it was 29s (xml) vs 14s (dynamic);
    • may be it could be harder to understand for people not familiar with xpath;

    pros

    • it's the same scope as your other queries, and that could be very handy. A few examples come to mind
      • you could query inserted and deleted tables inside your trigger (not possible with dynamic at all);
      • user don't have to have permissions on direct select from table. What I mean is if you have stored procedures layer and user have permissions to run sp, but don't have permissions to query tables directly, you still could use this query inside stored procedure;
      • you could query table variable you have populated in your scope (to pass it inside the dynamic SQL you have to either make it temporary table instead or create type and pass it as a parameter into dynamic SQL;
    • you can do this query inside the function (scalar or table-valued). It's not possible to use dynamic SQL inside the functions;

提交回复
热议问题