Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Transpose rows to column and join table

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.

like image 855
Sujithk109 Avatar asked Mar 05 '13 21:03

Sujithk109


People also ask

How do I convert a row data into a column?

Here's how you can transpose cell content: Copy the cell range. Select the empty cells where you want to paste the transposed data. On the Home tab, click the Paste icon, and select Paste Transpose.

How do you join a table conditionally?

A conditional column join is a fancy way to let us join to a single column and to two (or more) columns in a single query. We can accomplish this by using a case statement in the on clause of our join. A case statement allows us to test multiple conditions (like an if/else if/else) to produce a single value.


2 Answers

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

Sql Fiddle

like image 50
Michael Fredrickson Avatar answered Oct 12 '22 23:10

Michael Fredrickson


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 |
like image 41
Taryn Avatar answered Oct 12 '22 23:10

Taryn