Reputation: 61
Hi I have two tables Attribute, Instance
Attribute Table
id | key_info | value_info
2 | amount | 1009
2 | currency | USD
2 | Level | Level 5
3 | amount | 2017
3 | currency | CAD
Instance Table
id | status
2 | Pending
3 | Approved
I want to join two tables like this-
New table
id | amount | currrency | level | status
2 | 1001 | USD | Level 5 | Pending
3 | 2017 | CAD | | Approved
All the fields in the Attribute and Instance are optional except id.
Upvotes: 5
Views: 29252
Reputation: 247880
Starting in SQL Server 2005, the PIVOT
function can perform this conversion from rows to columns:
select id,
amount,
currency,
level,
status
from
(
select i.id, i.status,
a.key_info,
a.value_info
from instance i
inner join attribute a
on i.id = a.id
) src
pivot
(
max(value_info)
for key_info in (amount, currency, level)
) piv
See SQL Fiddle with Demo.
If you have an unknown number of key_values
then you can use dynamic SQL:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT distinct ',' + QUOTENAME(key_info)
from Attribute
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT id, ' + @cols + ', status from
(
select i.id, i.status,
a.key_info,
a.value_info
from instance i
inner join attribute a
on i.id = a.id
) x
pivot
(
max(value_info)
for key_info in (' + @cols + ')
) p '
execute(@query)
See SQL Fiddle with Demo. Both give the result:
| ID | AMOUNT | CURRENCY | LEVEL | STATUS |
-----------------------------------------------
| 2 | 1009 | USD | Level 5 | Pending |
| 3 | 2017 | CAD | (null) | Approved |
Upvotes: 9
Reputation: 37398
select
a.id,
max(case when a.key_info = 'amount' then a.value_info end) as amount,
max(case when a.key_info = 'currency' then a.value_info end) as currency,
max(case when a.key_info = 'level' then a.value_info end) as level,
i.status
from
attribute a
join instance i on a.id = i.id
group by
a.id,
i.status
Upvotes: 14