In order to get the result that you want, I would suggest a slightly different approach to this. Since you want to pivot on two columns of data Contacts
and Phone
, I would first unpivot these columns into multiple rows, then apply the PIVOT - I think it is easier to to that then trying to apply the PIVOT twice.
I see a few things that I would fix in your current query. The main part of you query that is joining to all of the tables has a couple of things to change. First, I would only create one Row
column:
row_number() over(partition by relation.company_id
order by contact.first_name, contact.last_name) row
This column would be partitioned by the company_Id
in the in the contact_company_relation
table. This new row number will be used for both the Contact
and the Phone
number columns.
Second, your current join to return the Phone
number appears to be incorrect. Your current code is using the main company
id but you want to join on each contact. Change your code from:
left join contact_phones phone
on company.id = phone.contact_id
to:
left join contact_phones phone
on contact.id = phone.contact_id
This will make your subquery:
select
contact.first_name + ' ' + contact.last_name as contact_name,
phone.display_phone,
company.company_name,
row_number() over(partition by relation.company_id
order by contact.first_name, contact.last_name) row
from contacts company
left join contact_company_relation relation
on company.id = relation.company_id
left join contacts contact
on relation.contact_id = contact.id
and contact.is_company = 0
left join contact_phones phone
on contact.id = phone.contact_id -- change to join on contact
where company.is_company = 1;
See SQL Fiddle with Demo. The data will now look like:
| CONTACT_NAME | DISPLAY_PHONE | COMPANY_NAME | ROW |
|--------------|---------------|--------------|-----|
| Ben Gurion | 2222222 | Analist | 1 |
| Ofer Jerus | 3333333 | Analist | 2 |
| Ori Reshef | 1111111 | Analist | 3 |
Once you have the data with the row number, you can unpivot the display_phone
and company_name
into multiple rows instead of columns. You didn't specify what version of SQL Server you are using but you can use either UNPIVOT or CROSS APPLY to do this. When you unpivot the data you will then use the Row
value to associate each contact
and phone
pair - this makes sure that each contact is still associated with the correct phone number. The code would be similar to:
;with cte as
(
-- query from above here
)
select compnay_name, col, value
from
(
select company_name,
col = col+'_'+cast(row as varchar(50)),
value
from cte
cross apply
(
select 'Contact', Contact_name union all
select 'Phone', display_phone
) c (col, value)
) src;
See SQL Fiddle with Demo. The data will now be in the format which has multiple rows for each company_name, contact and phone:
| COMPANY_NAME | COL | VALUE |
|--------------|-----------|------------|
| Analist | Contact_1 | Ben Gurion |
| Analist | Phone_1 | 2222222 |
| Analist | Contact_2 | Ofer Jerus |
| Analist | Phone_2 | 3333333 |
| Analist | Contact_3 | Ori Reshef |
| Analist | Phone_3 | 1111111 |
The final step would be to add the PIVOT function making the final code:
;with cte as
(
select
contact.first_name + ' ' + contact.last_name as contact_name,
phone.display_phone,
company.company_name,
row_number() over(partition by relation.company_id
order by contact.first_name, contact.last_name) row
from contacts company
left join contact_company_relation relation
on company.id = relation.company_id
left join contacts contact
on relation.contact_id = contact.id
and contact.is_company = 0
left join contact_phones phone
on contact.id = phone.contact_id -- change to join on contact
where company.is_company = 1
)
select company_name,
contact_1, contact_2, contact_3, contact_4, contact_5,
phone_1, phone_2, phone_3, phone_4, phone_5
from
(
select company_name,
col = col+'_'+cast(row as varchar(50)),
value
from cte
cross apply
(
select 'Contact', Contact_name union all
select 'Phone', display_phone
) c (col, value)
) src
pivot
(
max(value)
for col in (contact_1, contact_2, contact_3, contact_4, contact_5,
phone_1, phone_2, phone_3, phone_4, phone_5)
) p;
See SQL Fiddle with Demo. The final result looks like:
| COMPANY_NAME | CONTACT_1 | CONTACT_2 | CONTACT_3 | CONTACT_4 | CONTACT_5 | PHONE_1 | PHONE_2 | PHONE_3 | PHONE_4 | PHONE_5 |
|--------------|------------|------------|------------|-----------|-----------|---------|---------|---------|---------|---------|
| Analist | Ben Gurion | Ofer Jerus | Ori Reshef | (null) | (null) | 2222222 | 3333333 | 1111111 | (null) | (null) |
| Bar Net | Dima Brods | Maya Leshe | Yossi Farc | (null) | (null) | 7777777 | 4444444 | 6666666 | (null) | (null) |