Question

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.

Was it helpful?

Solution

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

OTHER TIPS

Maybe you want something like:

update pi 
 set 
  pi.height = paH.attribute_value,
  pi.weight = paW.attribute_value,
  pi.eye_color = paE.attribute_value
 from 
  @people_info pi 
   inner join dbo.HR.person_attributes paH on pi.person_id = paH.person_id 
                                            and paH.attribute_type_id = 'Height'
   inner join dbo.HR.person_attributes paW on pi.person_id = paW.person_id 
                                            and paW.attribute_type_id = 'Weight'
   inner join dbo.HR.person_attributes paE on pi.person_id = paE.person_id 
                                            and paE.attribute_type_id = 'EyeColor'
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top