2013-08-08 11 views
13

Ich entschuldige mich für das Einreichen einer anderen Frage zu diesem Thema, aber ich habe viele der Antworten zu diesem Thema gelesen und ich kann nicht scheinen, um es für mich zu arbeiten.SQL Server 2008 Vertikale Daten zu Horizontal

Ich habe drei Tabellen, die ich beitreten und Info auf ziehen muss. Eine der Tabellen besteht nur aus 3 Spalten und speichert die Daten vertikal. Ich möchte diese Daten in ein horizontales Format übertragen.

Die Daten werden wie folgt aussehen, wenn ich kommen und ziehen gerade:

SELECT 
    a.app_id, 
    b.field_id, 
    c.field_name, 
    b.field_value 
FROM table1 a 
JOIN table2 b ON a.app_id = b.app_id 
JOIN table3 c ON b.field_id = c.field_id --(table3 is a lookup table for field names) 

Ergebnis:

app_id | field_id | field_name | field_value 
----------------------------------------------------- 
1234 | 101  | First Name |  Joe 
1234 | 102  |  Last Name |  Smith 
1234 | 105  |  DOB  | 10/15/72 
1234 | 107  | Mailing Addr | PO BOX 1234 
1234 | 110  |  Zip  |  12345  
1239 | 101  | First Name |  Bob 
1239 | 102  |  Last Name |  Johnson 
1239 | 105  |  DOB  | 12/01/78 
1239 | 107  | Mailing Addr | 1234 N Star Ave 
1239 | 110  |  Zip  |  12456 

Stattdessen würde ich es mag so aussehen:

app_id | First Name | Last Name | DOB | Mailing Addr | Zip 
-------------------------------------------------------------------------- 
1234 | Joe  |  Smith  | 10/15/72 | PO BOX 1234 | 12345  
1239 | Bob  | Johnson | 12/01/78 | 1234 N Star Ave | 12456 

In der Vergangenheit habe ich einfach alle field_id's, die ich benötigt habe, in meinen Daten nachgeschlagen und CASE-Statements für jeden erstellt. Die App, die die Benutzer verwenden, enthält Daten für mehrere Produkte und jedes Produkt enthält unterschiedliche Felder. Betrachtet man die Anzahl der unterstützten Produkte und die Anzahl der Felder für jedes Produkt (viele, viel mehr als das grundlegende Beispiel, das ich oben gezeigt habe), braucht man viel Zeit, um sie aufzusuchen und riesige Teile der CASE-Anweisungen auszugeben.

Ich frage mich, ob es da draußen einen Cheat-Code gibt, um das zu erreichen, was ich brauche, ohne die field_ids nachschlagen und Dinge aufschreiben zu müssen. Ich weiß, dass die PIVOT-Funktion wahrscheinlich das ist, wonach ich suche, aber ich kann nicht scheinen, dass es richtig funktioniert.

Denkst du Jungs könnte helfen?

Antwort

29

Sie die PIVOT Funktion können Sie Ihre Datenzeilen in Spalten konvertieren.

Ihre ursprüngliche Abfrage kann verwendet werden, um alle Daten abzurufen. Die einzige Änderung, die ich vornehmen würde wäre, die Spalte b.field_id auszuschließen, da dies die endgültige Anzeige des Ergebnisses ändert.

Wenn Sie eine Liste der bekannten field_name Werte haben, die Sie in Spalten umwandeln möchten, dann können Sie hart Code Anfrage:

select app_id, 
    [First Name], [Last Name], [DOB], 
    [Mailing Addr], [Zip] 
from 
(
    SELECT 
    a.app_id, 
    c.field_name, 
    b.field_value 
    FROM table1 a 
    INNER JOIN table2 b 
    ON a.app_id = b.app_id 
    INNER JOIN table3 c 
    ON b.field_id = c.field_id 
) d 
pivot 
(
    max(field_value) 
    for field_name in ([First Name], [Last Name], [DOB], 
        [Mailing Addr], [Zip]) 
) piv; 

Siehe SQL Fiddle with Demo.

Aber wenn Sie eine unbekannte Anzahl von Werten für field_name gehen müssen, dann müssen Sie die dynamische SQL implementieren, um die Ergebnisse zu erhalten:

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

select @cols = STUFF((SELECT ',' + QUOTENAME(Field_name) 
        from Table3 
        group by field_name, Field_id 
        order by Field_id 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query = 'SELECT app_id,' + @cols + ' 
      from 
      (
       SELECT 
       a.app_id, 
       c.field_name, 
       b.field_value 
       FROM table1 a 
       INNER JOIN table2 b 
       ON a.app_id = b.app_id 
       INNER JOIN table3 c 
       ON b.field_id = c.field_id 
      ) x 
      pivot 
      (
       max(field_value) 
       for field_name in (' + @cols + ') 
      ) p ' 

execute sp_executesql @query; 

See. Beides dies gibt ein Ergebnis:

| APP_ID | FIRST NAME | LAST NAME |  DOB | MAILING ADDR | ZIP | 
------------------------------------------------------------------------ 
| 1234 |  Joe |  Smith | 10/15/72 |  PO Box 1234 | 12345 | 
| 1239 |  Bob | Johnson | 12/01/78 | 1234 N Star Ave | 12456 | 
+4

Das ist genau das, was ich brauchte.Ich habe nicht den Repräsentanten, der dich aufmuntert, aber wenn irgendjemand hier draußen das sieht, bitte stimme für mich! –

3

Versuchen Sie, diese

SELECT 
    [app_id] 
    ,MAX([First Name]) AS [First Name] 
    ,MAX([Last Name]) AS [Last Name] 
    ,MAX([DOB]) AS [DOB] 
    ,MAX([Mailing Addr]) AS [Mailing Addr] 
    ,MAX([Zip]) AS [Zip] 
FROM Table1 
PIVOT 
(
    MAX([field_value]) FOR [field_name] IN ([First Name],[Last Name],[DOB],[Mailing Addr],[Zip]) 
) T 
GROUP BY [app_id] 

SQL FIDDLE DEMO

0

bluefeet Antwort war die richtige für mich, aber ich brauchte verschiedene auf der Spaltenliste:

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

select @cols = STUFF((SELECT Distinct ',' + QUOTENAME(Field_name) 
       from Table3 
       group by field_name, Field_id 
       order by ',' + QUOTENAME(Field_name) 
     FOR XML PATH(''), TYPE 
     ).value('.', 'NVARCHAR(MAX)') 
    ,1,1,'') 

set @query = 'SELECT app_id,' + @cols + ' 
     from 
     (
      SELECT 
      a.app_id, 
      c.field_name, 
      b.field_value 
      FROM table1 a 
      INNER JOIN table2 b 
      ON a.app_id = b.app_id 
      INNER JOIN table3 c 
      ON b.field_id = c.field_id 
     ) x 
     pivot 
     (
      max(field_value) 
      for field_name in (' + @cols + ') 
     ) p ' 

execute sp_executesql @query;