I have data like this:
Product Group Product Level Quatity Sold Trend
==============================================================
Group 1
You could get the desired result by implementing the PIVOT function, but I would first UNPIVOT your multiple columns of Quantity Sold
and Trend
. The unpivot process will convert them from multiple columns into multiple rows of data.
Since you are using SQL Server 2008+, you can use CROSS APPLY
with VALUES
to unpivot the data:
select [Product Group],
col, value
from yourtable
cross apply
(
values
([Product Level], cast([Quatity Sold] as varchar(10))),
([Product Level]+'trend', [trend])
) c (col, value);
See SQL Fiddle with Demo This converts your table data into the format:
| PRODUCT GROUP | COL | VALUE |
|---------------|---------|-------|
| Group 1 | L1 | 10 |
| Group 1 | L1trend | up |
| Group 1 | L2 | 20 |
| Group 1 | L2trend | up |
| Group 1 | L3 | 30 |
| Group 1 | L3trend | down |
Now you can easily apply the PIVOT function:
select [Product Group],
L1, L1trend,
L2, L2trend,
L3, L3trend,
L4, L4trend
from
(
select [Product Group],
col, value
from yourtable
cross apply
(
values
([Product Level], cast([Quatity Sold] as varchar(10))),
([Product Level]+'trend', [trend])
) c (col, value)
) d
pivot
(
max(value)
for col in (L1, L1trend, L2, L2trend,
L3, L3trend, L4, L4trend)
) piv;
See SQL Fiddle with Demo. This gives you a final result of:
| PRODUCT GROUP | L1 | L1TREND | L2 | L2TREND | L3 | L3TREND | L4 | L4TREND |
|---------------|----|---------|----|---------|----|---------|--------|---------|
| Group 1 | 10 | up | 20 | up | 30 | down | (null) | (null) |
| Group 2 | 20 | up | 40 | up | 60 | down | 80 | down |
You can potentially do this using correlated subqueries:
select productGroup as [Product Group]
, (select sum(quantitySold) from myTable where productGroup = a.productGroup and productLevel = 'L1') as L1
, (select max(trend) from myTable where productGroup = a.productGroup and productLevel = 'L1') as L1Trend
, (select sum(quantitySold) from myTable where productGroup = a.productGroup and productLevel = 'L2') as L2
, (select max(trend) from myTable where productGroup = a.productGroup and productLevel = 'L2') as L2Trend
-- etc.
from myTable a
group by productGroup
order by productGroup
Here's an example SqlFiddle.
It may help you to see it this way before you use the PIVOT
keyword.
If you don't know how many productLevel values you have, you'd need a dynamic solution, however.
if you prefer to use pivot you can try this one:
select productgroup,
coalesce(L1up,L1down,'') L1, case when L1up is not null then 'up' when L1down is not null then 'down' else '' end L1trend,
coalesce(L2up,L2down,'') L2, case when L2up is not null then 'up' when L2down is not null then 'down' else '' end L2trend,
coalesce(L3up,L3down,'') L3, case when L3up is not null then 'up' when L3down is not null then 'down' else '' end L3trend,
coalesce(L4up,L4down,'') L4, case when L4up is not null then 'up' when L4down is not null then 'down' else '' end L4trend
from
(
select productgroup, [L1up],[L2up],[L3up],[L4up],[L1down],[L2down],[L3down],[L4down]
from (select productgroup, productlevel+trend pt, quantity from mytable) t
PIVOT (MAX(quantity)
FOR pt IN([L1up],[L2up],[L3up],[L4up],[L1down],[L2down],[L3down],[L4down] )) as p
) t