Estoy intentando escribir una consulta no dinámica que convierte los datos de usuario almacenados en columnas en una fila por usuario. Aquí está lo que tengo hasta ahora, gracias a otras publicaciones de SO: http://sqlfiddle.com/#!18/fa77c/2

Error (tiene sentido porque "correo electrónico" es una cadena almacenada en la columna Nombre):

Nombre de columna no válido 'correo electrónico'.

Objetivo final:

ID Email   Phone
1  a@a.com 111
2  b@b.com 222
3  NULL    333
0
Rilcon42 21 may. 2018 a las 17:58

4 respuestas

La mejor respuesta

No estoy seguro de que univivot sea realmente lo que quieres aquí. Puedes hacer esto bastante fácilmente con algo de agregación.

select ac.AccountID
    , max(case when c.Name = 'email' then c.Data end) as Email
    , max(case when c.Name = 'phone' then c.Data end) as Phone
from AccountContacts ac
left join Contacts c on c.ID = ac.ContactID 
group by ac.AccountID

Tenga en cuenta que la razón por la que lucha aquí es porque su estructura de datos es un antipatrón conocido como EAV (valor de atributo de entidad). Es un verdadero dolor trabajar con ellos. Si fuera posible, arreglar su estructura de datos sería un gran plan.

2
Sean Lange 21 may. 2018 a las 15:31

Según los resultados deseados y la configuración proporcionada en su violín de SQL, está buscando PIVOTAR sus datos, no UNPIVOT.

Esta consulta hace el truco:

with src as (
  select accountid
       , name
       , data
    from accountcontacts ac
    join contacts c
      on c.id = ac.contactid
)
select *
  from src
  pivot (max(data)
    for name in ([email],[phone])) pvt
1
Sentinel 21 may. 2018 a las 15:25
  select a.data email, b.data phone from  
   (select * from Contacts a 
    join AccountContacts b on a.id=b.ContactID where name='email')a
 full join (
     select * from Contacts a 
     join AccountContacts b on a.id=b.ContactID where name='phone'
  )b on a.AccountID=b.AccountID
0
Daniel Marcus 21 may. 2018 a las 15:06

Puede hacer la agregación condicional :

SELECT ac.AccountID as ID,
       max(case when c.name = 'email' then c.data end) email,
       max(case when c.name = 'phone' then c.data end) phone
from Contacts c
left join AccountContacts ac on ac.ContactID = c.id
group by ac.AccountID;
1
Yogesh Sharma 21 may. 2018 a las 15:30