The sql server updates multiple columns with a selection of a join of a table variable and a db table

advertisements

I have the classical person -> person attributes scheme. So, like this: person(PK) <- person_attribute(FK)

What I need is a query to get one row where a person is joined with her attributes. For example, to transform:

Person:
{ ID = 123456, Name = 'John Smith', Age = 25 }
Attributes:
1) { PersonID = 123456, AttributeTypeID = 'Height', AttributeValue = '6'6'''}
2) { PersonID = 123456, AttributeTypeID = 'Weight', AttributeValue = '220lbs'}
3) { PersonID = 123456, AttributeTypeID = 'EyeColor', AttributeValue = 'Blue'}

To:

PersonWithAttributes
{
 ID = 123456, Name = 'John Smith', Age = 25, Height = '6'6''', Weight = '220lbs', EyeColor = 'Blue'
}

To make things worse my persons are in a table variable.

So, I have (in a sp with a parameter of person_id):

--result table
declare @people_info table
(
person_id int,
name nvarchar(max),
age int,
height nvarchar(10) null,
weight nvarchar(10) null,
eye_color nvarchar(16) null
)

insert into @people_info
 select person_id, name, age, null, null, null
  from dbo.HR.people where person_id = @person_id

update pi
 set
  pi.height = (select pa.attribute_value where pa.attribute_type_id = 'Height'),
  pi.height = (select pa.attribute_value where pa.attribute_type_id = 'Weight'),
  pi.eye_color = (select pa.attribute_value where pa.attribute_type_id = 'EyeColor')
 from
  @people_info pi
   inner join dbo.HR.person_attributes pa on pi.person_id = pa.person_id

select * from @people_info

Which of course does not work for some reason. If I query the two joined tables and select "pa.attribute_value where pa.attribute_type_id = 'someval'" I get the correct value. But the update does not work.

Of course, I can write this as three updates, but I am thinking that it will be faster to do one join and then to filter in the update clause.

Also, please keep in mind that my attributes are spread over three tables, not just the attributes table. So, this is why I have the table variable.

Any help is very welcome. Maybe I am going about this the wrong way. Performance matters. What is the most performant way to accomplish this?

Thank you very much.


Try this code for update with pivot:

    update
        pi
    set
        pi.height = pa.Height
        pi.weight = pa.Weight
        pi.eye_color = pa.EyeColor
    from
        @people_info pi
    inner join
        (
            SELECT
                 person_id
                ,[Height] Height
                ,[Weight] Weight
                ,[EyeColor] EyeColor
            FROM
            (
                SELECT
                      attribute_type_id
                    , attribute_value
                    , person_id
                FROM
                    dbo.HR.person_attributes pa
            ) pa
            PIVOT
            (
                MAX(attribute_value) FOR attribute_type_id IN ([Height],[Weight],[EyeColor])
            )pvt

        ) pa
    on
        pi.person_id = pa.person_id