2010-10-24 8 views
4

J'ai une table dans la base de données qui ressemble à ceci:tables Convertir avec « id, attribut, valeur » colonnes « id, attribut1, Attribut2, ... »

CustomerId Attribute Value 
================================ 
30   Name   John 
30   Surname  Smith 
30   Phone  555123456 

à faire un peu d'utilisation des données dont j'ai besoin pour le faire paraître. comme ceci:

CustomerId Name Surname Phone 
====================================== 
30   John Smith  555123456 

Je sais que je peux créer une procédure stockée ou une fonction à valeur de table qui le fera pour moi, mais je me demande quel serait le meilleur choix ici? Peut-être que je peux le faire avec une requête SQL select intelligente seulement?

Répondre

4

Dans ce SQL Server 2005 ou version ultérieure, vous pouvez utiliser PIVOT:

with Customers (CustomerId, Attribute, Value) 
as 
(
    select 30, 'Name', 'John' 
    union 
    select 30, 'Surname', 'Smith' 
    union 
    select 30, 'Phone', '551123456' 
    union 
    select 40, 'Name', 'Mary' 
    union 
    select 40, 'Surname', 'Johnson' 
    union 
    select 40, 'Phone', '9991111234' 
) 
select CustomerId, Name, Surname, Phone 
from Customers 
pivot 
(
    min(Value) 
    for Attribute in (Name, Surname, Phone) 
) as PivotTable 

Ou une solution qui n'utilise pas PIVOT:

/* with cte defined as above */ 
select CustomerId, 
    max(case Attribute when 'Name' then Value else '' end) Name, 
    max(case Attribute when 'Surname' then Value else '' end) Surname, 
    max(case Attribute when 'Phone' then Value else '' end) Phone 
from Customers 
group by CustomerId 
+0

Merci beaucoup! C'est une réponse dont je n'aurais même pas rêvé! – kubal5003

1

Compte tenu du scénario suivant:

create table vertical(
CustomerID int, 
attribute varchar(255), 
value varchar(255) 
) 

create table horizontal(
CustomerID int, 
name varchar(255), 
surname varchar(255), 
phone varchar(255) 
) 

insert into vertical 
    select 30, 'Name', 'John' 
insert into vertical 
    select 30, 'Surname', 'Smith' 
insert into vertical 
    select 30, 'Phone', '551123456' 
insert into vertical 
    select 40, 'Name', 'Mary' 
insert into vertical 
    select 40, 'Surname', 'Johnson' 
insert into vertical 
    select 40, 'Phone', '9991111234' 
insert into vertical 
    select 50, 'Surname', 'Manuel' 
insert into vertical 
    select 50, 'Phone', '423' 

exécutant cet insert sortie doit

insert into horizontal (CustomerID, name, surname, phone) 
select c.CustomerID, n.value as name, s.value as surname, ph.value as phone 
from 
(select distinct CustomerID from vertical) as c 
left join vertical n 
    on c.CustomerID = n.CustomerID and n.attribute = 'name' 
left join vertical s 
    on c.CustomerID = s.CustomerID and s.attribute = 'Surname' 
left join vertical ph 
    on c.CustomerID = ph.CustomerID and ph.attribute = 'Phone' 

ceci:

ID Name Surname Phone 
-- ---- ------- ----- 
30 John Smith 551123456 
40 Mary Johnson 9991111234 
50 NULL Manuel 423 

Où:

de:select distinct CustomerID from vertical apporte tous les clients qui ont au moins un attribut. Chaque jointure à gauche renvoie la valeur correspondante pour chaque attribut.

La jointure à gauche a été utilisée pour s'assurer que la ligne client sera insérée même s'il manque des attributs au client, auquel cas NULL sera inséré.

table source nommée verticale est celle avec les valeurs d'attribut

table cible horizontale nommée est votre sortie désirée

+0

Merci, l'auto-participation était toujours une sorte d'option, mais personnellement, je ne l'aime pas, parce que c'est moche. Pivot semble être une solution bien meilleure. – kubal5003

Questions connexes