简体   繁体   中英

TSQL Columns to rows

I have the following table columns (with sample data)

[Member_ID] - [GM1] - [GM2] ... [GM12] - [CATEGORY]
165 - 30 - 50 ... 40 - Products
165 - 70 - 60 ... 70 - Service
189 - 50 - 60 ... 50 - Products
189 - 40 - 30 ... 40 - Service

Each GM column is for each month.

At the end I would like to have something like this

[MemberID] - [GMP] - [GMS] - [MonthNumbr]
165 - 30 - 70 - 1
165 - 50 - 60 - 2
189 - 50 - 40 - 1
...
165 - 40 - 70 - 12
189 - 50 - 40 - 12

Where GMP is the GM for that month for Category Product and GMS is the GM for that month for Service

I tried unpivot and cross apply, but I think it is way over my experience and keep getting stuck.

thanks in advance!

I like to use outer apply for this purpose . . . then aggregation helps:

select v.member_id, v.monthnumber,
       max(case when category = 'products' then gm end) as gmp,
       max(case when category = 'service' then gm end) as gms
from t outer apply
     (values (t.member_id, 1, t.gm1, t.category),
             (t.member_id, 2, t.gm2, t.category),
              . . .
     ) v(member_id, monthnumber, gm, category)
group by v.member_id, v.monthnumber;

EDIT:

It might be more efficient to do the aggregation in the subquery:

select v.*
from t outer apply
     (select v.member_id, v.monthnumber,
             max(case when category = 'products' then gm end) as gmp,
             max(case when category = 'service' then gm end) as gms
      from (values (t.member_id, 1, t.gm1, t.category),
                   (t.member_id, 2, t.gm2, t.category),
                   . . .
           ) v(member_id, monthnumber, gm, category)
     ) v;

(Because of the nature of the aggregation algorithms, a bunch of small aggregations should be more efficient than one large one.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM