2013-06-13 4 views
1

Ok dire que j'ai quelque chose comme ceci:combiner plusieurs lignes sql avec des colonnes différentes

ID | Name | Address 
1 | Bob | 123 Fake Street 
1 | Bob | 221 Other Street 

fait en faisant quelque chose comme:

select p.ID, p.Name a.Address from People p 
inner join Addresses a on a.OwnerID = p.ID 

Est-il possible de transformer en

ID | Name | Address_1 |  Address_2 | etc... 
1 | Bob | 123 Fake Street | 221 Other street | etc 

J'ai vu des choses qui font des valeurs séparées par des virgules dans une colonne mais je ne veux pas que je veuille des colonnes distinctes. J'interroge cela en utilisant MSSQL et C# Je ne sais pas si cela change quelque chose. Aussi, c'est un scénario inventé qui est juste similaire à ce que je fais, donc la structure réelle des tables ne peut pas être changée.

Quelqu'un a des suggestions?

+0

Pourquoi avez-vous besoin de colonnes? Êtes-vous en train de charger des données dans 'DataTable' et de les montrer dans un certain contrôle de la grille? –

+0

Oui, il pourrait potentiellement être passé à un DataTable. Mais maintenant les valeurs sont utilisées pour charger un objet. Je ne veux juste pas un tas de cas spéciaux dans mon code vérifiant l'ID similaire et ensuite l'analyser. Je veux le rendre aussi général que possible – eric

Répondre

4

Vous pouvez utiliser la fonction PIVOT pour obtenir le résultat, mais vous devrez également l'implémenter en utilisant un row_number() afin de pouvoir convertir plusieurs adresses par personne en colonnes.

Si vous aviez un nombre connu d'adresses, alors vous coder en dur la requête:

select id, name, address_1, address_2 
from 
(
    select p.id, p.name, a.address, 
    'Address_'+cast(row_number() over(partition by p.id 
             order by a.ownerid) as varchar(10)) rn 
    from people p 
    inner join addresses a 
    on p.id = a.ownerid 
) d 
pivot 
(
    max(address) 
    for rn in (address_1, address_2) 
) piv; 

Voir SQL Fiddle with Demo.

Mais si votre cas, vous aurez un nombre inconnu d'adresses par personne si vous voulez utiliser SQL dynamique et le placer dans une procédure stockée à exécuter:

DECLARE @cols AS NVARCHAR(MAX), 
    @query AS NVARCHAR(MAX) 

select @cols = STUFF((SELECT distinct ',' + QUOTENAME('Address_'+d.rn) 
        from 
        (
         select cast(row_number() over(partition by a.ownerid 
             order by a.ownerid) as varchar(10)) rn 
         from Addresses a 
        ) d 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query = 'SELECT id, name, ' + @cols + ' 
      from 
      (
       select p.id, p.name, a.address, 
       ''Address_''+cast(row_number() over(partition by p.id 
                order by a.ownerid) as varchar(10)) rn 
       from people p 
       inner join addresses a 
       on p.id = a.ownerid 
      ) d 
      pivot 
      (
       max(address) 
       for rn in (' + @cols + ') 
      ) p ' 

execute(@query); 

Voir SQL Fiddle with Demo. Ces deux donnent un résultat:

| ID | NAME |   ADDRESS_1 |  ADDRESS_2 | ADDRESS_3 | 
---------------------------------------------------------------- 
| 1 | Bob | 123 Fake Street | 221 Other Street | (null) | 
| 2 | Jim | 123 e main street |   (null) | (null) | 
| 3 | Tim | 489 North Drive | 56 June Street | 415 Lost | 
+0

Goodone Bluefeet –

+0

Un problème que je ne peux pas créer une procédure stockée (ne pas avoir d'autorisations sauf select essentiellement). Existe-t-il un moyen de procéder de manière générale sans procédure stockée? – eric

+0

@eric Lorsque vous travaillez avec SQL dynamique, il doit être implémenté dans une procédure stockée. Le problème est que vous aurez un nombre inconnu d'adresses pour chaque personne. Avez-vous une limite sur le nombre d'adresses qu'une personne peut avoir? – Taryn

Questions connexes