2013-04-17 15 views
8

Ho una tabella che sembra simile a questo qui:SQL - Prendere i dati da più righe in un'unica riga

SetId  AppCode  AppEventId  EventId  FieldId  ValueData 
2012/2013  1000   361616    16   1   UNI  
2012/2013  1000   361616    16   2   Isolation 
2012/2013  1000   361616    16   3   DN 
2012/2013  1050   378194    16   1   BUL 
2012/2013  1050   378194    16   2   Isolation 
2012/2013  1050   378194    16   3   RD 

Vorrei in grado di combinare tutti i dati quando hanno lo stesso AppCode.

Quale sarebbe simile a questa:

SetId  AppCode  AppEventId  EventId  ValueData1  ValueData2  ValueData3 
2012/2013  1000   361616    16   UNI   Isolation  DN 
2012/2013  1050   378194    16   BUL   Isolation  RD 
+3

** PIVOT ** È la risposta. Mostraci cosa hai provato. – Luv

+0

Ciao, credo che la tua tabella non segua le regole di normalizzazione. dovresti prima riconsiderare la struttura del tuo tavolo. –

+0

Grazie Luv guarderò su PIVOT. – dawsonz

risposta

14

Prova questo

SELECT SetId, AppCode, AppEventId, EventId 
    ,max(CASE WHEN FieldId = 1 THEN ValueData END) AS ValueData1 
    ,max(CASE WHEN FieldId = 2 THEN ValueData END) AS ValueData2 
    ,max(CASE WHEN FieldId = 3 THEN ValueData END) AS ValueData3 
    FROM Table_Name 
    GROUP BY SetId,AppCode,AppEventId,EventId 
+0

Funziona davvero bene, grazie Vassy. Molto apprezzato. – dawsonz

+0

Sono contento che abbia aiutato – bvr

+0

@bvr lo stesso non funziona per me con SQL Server 2008. – User

2

UPDATE:

Migliorare risposta -

DECLARE @temp TABLE 
(
     SetId VARCHAR(9)  
     , AppCode CHAR(4)  
     , AppEventId INT  
     , EventId INT  
     , FieldId TINYINT  
     , ValueData VARCHAR(50) 
) 

INSERT INTO @temp (SetId, AppCode, AppEventId, EventId, FieldId, ValueData) 
VALUES 
    ('2012/2013',  '1000',   361616,    16,   1,   'UNI'),  
    ('2012/2013',  '1000',   361616,    16,   2,   'Isolation'), 
    ('2012/2013',  '1000',   361616,    16,   3,   'DN'), 
    ('2012/2013',  '1050',   378194,    16,   1,   'BUL'), 
    ('2012/2013',  '1050',   378194,    16,   2,   'Isolation'), 
    ('2012/2013',  '1050',   378194,    16,   3,   'RD') 

;WITH tbl AS 
(
    SELECT 
      PK = t.SetId + t.AppCode + CAST(AppEventId AS VARCHAR(10)) + CAST(EventId AS VARCHAR(5)) 
      , t.SetId 
      , t.AppCode 
      , t.AppEventId 
      , t.EventId 
      , t.FieldId 
      , t.ValueData 
    FROM @temp t 
) 
SELECT DISTINCT 
     t.SetId 
    , t.AppCode 
    , t.AppEventId 
    , t.EventId 
    , t2.ValueData 
    , t3.ValueData 
    , t4.ValueData 
FROM tbl t 
JOIN tbl t2 ON t.PK = t2.PK AND t2.FieldId = 1 
JOIN tbl t3 ON t.PK = t3.PK AND t3.FieldId = 2 
JOIN tbl t4 ON t.PK = t4.PK AND t4.FieldId = 3 

Non elegante, ma funziona -

DECLARE @temp TABLE 
(
     SetId VARCHAR(9)  
     , AppCode CHAR(4)  
     , AppEventId INT  
     , EventId INT  
     , FieldId TINYINT  
     , ValueData VARCHAR(50) 
) 

INSERT INTO @temp (SetId, AppCode, AppEventId, EventId, FieldId, ValueData) 
VALUES 
    ('2012/2013',  '1000',   361616,    16,   1,   'UNI'),  
    ('2012/2013',  '1000',   361616,    16,   2,   'Isolation'), 
    ('2012/2013',  '1000',   361616,    16,   3,   'DN'), 
    ('2012/2013',  '1050',   378194,    16,   1,   'BUL'), 
    ('2012/2013',  '1050',   378194,    16,   2,   'Isolation'), 
    ('2012/2013',  '1050',   378194,    16,   3,   'RD') 

SELECT t.SetId 
    , t.AppCode 
    , t.AppEventId 
    , t.EventId 
    , t2.ValueData 
    , t3.ValueData 
    , t4.ValueData 
FROM (
    SELECT 
      t.SetId 
     , t.AppCode 
     , t.AppEventId 
     , t.EventId 
     , FieldId1 = MAX(CASE WHEN t.FieldId = 1 THEN t.FieldId END) 
     , FieldId2 = MAX(CASE WHEN t.FieldId = 2 THEN t.FieldId END) 
     , FieldId3 = MAX(CASE WHEN t.FieldId = 3 THEN t.FieldId END) 
    FROM @temp t 
    GROUP BY 
      t.SetId 
     , t.AppCode 
     , t.AppEventId 
     , t.EventId 
) t 
JOIN @temp t2 ON t.SetId = t2.SetId 
     AND t.AppCode = t2.AppCode 
     AND t.AppEventId = t2.AppEventId 
     AND t.EventId = t2.EventId 
     AND t2.FieldId = 1 
JOIN @temp t3 ON t.SetId = t3.SetId 
     AND t.AppCode = t3.AppCode 
     AND t.AppEventId = t3.AppEventId 
     AND t.EventId = t3.EventId 
     AND t3.FieldId = 2 
JOIN @temp t4 ON t.SetId = t4.SetId 
     AND t.AppCode = t4.AppCode 
     AND t.AppEventId = t4.AppEventId 
     AND t.EventId = t4.EventId 
     AND t4.FieldId = 3 
7

Questo può essere fatto applicando la funzione PIVOT che è stato reso disponibile a partire da SQL Server 2005.

Se si dispone di un numero noto o un insieme di valori che si desidera trasformare in colonne , poi il ou può hard-code della query:

select setid, appcode, appeventid, 
    eventid, 
    ValueData1, ValueData2, ValueData3 
from 
(
    select setid, appcode, appeventid, 
    eventid, 
    'ValueData'+cast(FieldId as varchar(10)) FieldId, 
    ValueData 
    from yt 
) d 
pivot 
(
    max(ValueData) 
    for FieldId in (ValueData1, ValueData2, ValueData3) 
) piv; 

Vedi SQL Fiddle with Demo.

Ma se si dispone di un numero imprecisato di valori, allora si avrà bisogno di utilizzare SQL dinamico:

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

select @cols = STUFF((SELECT distinct ',' + QUOTENAME('ValueData'+cast(FieldId as varchar(10))) 
        from yt 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query = 'SELECT setid, appcode, appeventid, 
        eventid,' + @cols + ' 
      from 
      (
       select setid, appcode, appeventid, 
        eventid, 
        ''ValueData''+cast(FieldId as varchar(10)) FieldId, 
        ValueData 
       from yt 
      ) x 
      pivot 
      (
       max(ValueData) 
       for FieldId in (' + @cols + ') 
      ) p ' 

execute(@query); 

Vedi SQL Fiddle with Demo. Entrambe le query danno lo stesso risultato:

|  SETID | APPCODE | APPEVENTID | EVENTID | VALUEDATA1 | VALUEDATA2 | VALUEDATA3 | 
------------------------------------------------------------------------------------- 
| 2012/2013 | 1000 |  361616 |  16 |  UNI | Isolation |   DN | 
| 2012/2013 | 1050 |  378194 |  16 |  BUL | Isolation |   RD | 
Problemi correlati