The simplest way to get the result would be to use an aggregate function along with a CASE expression:
select
periodid,
periodname,
max(case when productname = 'A' then productid end) A_ID,
max(case when productname = 'A' then Productvalue end) A,
max(case when productname = 'B' then productid end) B_ID,
max(case when productname = 'B' then Productvalue end) B,
max(case when productname = 'C' then productid end) C_ID,
max(case when productname = 'C' then Productvalue end) C
from yourtable
group by periodid, periodname
order by periodid;
See SQL Fiddle with Demo.
However, if you want to use the PIVOT function to get the result I would first unpivot the productid
and productvalue
column first, so you no longer have multiple columns but multiple rows of this data. There are several ways that you can unpivot the data, you can use the unpivot function or you can use CROSS APPLY with a UNION ALL or VALUES (if you are using SQL Server 2008+). Since you are using SQL Server 2008 R2, here is how you can use CROSS APPLY with VALUES to unpivot the multiple columns:
select periodid, periodname,
col = productname+col,
value
from yourtable
cross apply
(
values
('_ID', ProductID),
('', Productvalue)
) c (col, value)
See SQL Fiddle with Demo. This gets your data into the format:
| PERIODID | PERIODNAME | COL | VALUE |
|----------|------------|------|-------|
| 10 | Jan | A_ID | 100 |
| 10 | Jan | A | 15 |
| 20 | Feb | A_ID | 100 |
| 20 | Feb | A | 25 |
| 30 | Mar | A_ID | 100 |
Now you can easily apply the PIVOT function to this data:
select periodid, periodname,
A_ID, A, B_ID, B, C_ID, C
from
(
select periodid, periodname,
col = productname+col,
value
from yourtable
cross apply
(
values
('_ID', ProductID),
('', Productvalue)
) c (col, value)
) d
pivot
(
max(value)
for col in (A_ID, A, B_ID, B, C_ID, C)
) piv
order by periodid;
See SQL Fiddle with Demo.
Finally if you have an unknown number of product names, then you can use dynamic SQL:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(productname+col)
from yourtable
cross apply
(
select '_ID', 1 union all
select '', 2
) c (col, so)
group by col, so, productname
order by productname, so
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT periodid, periodname,' + @cols + '
from
(
select periodid, periodname,
col = productname+col,
value
from yourtable
cross apply
(
values
(''_ID'', ProductID),
('''', Productvalue)
) c (col, value)
) x
pivot
(
max(value)
for col in (' + @cols + ')
) p
order by periodid'
execute sp_executesql @query;
See SQL Fiddle with Demo. All versions give a result:
| PERIODID | PERIODNAME | A_ID | A | B_ID | B | C_ID | C |
|----------|------------|------|----|------|----|------|----|
| 10 | Jan | 100 | 15 | 200 | 12 | 300 | 22 |
| 20 | Feb | 100 | 25 | 200 | 14 | 300 | 23 |
| 30 | Mar | 100 | 35 | 200 | 18 | 300 | 38 |