2013-08-08 37 views
13

Bu konuyla ilgili başka bir soru göndermek için özür dilerim, ancak bu konudaki cevapların çoğunu okudum ve benim için işe yaramayacak gibi görünmüyorum.SQL Server 2008 Dikey verilere yatay

Üç tabloya katılıyorum ve bilgi çekmem gerekiyor. Tablolardan biri sadece 3 sütundur ve verileri dikey olarak depolar. Bu verileri yatay bir formatta aktarmak istiyorum.

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) 

Sonuç: Yerine

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 

, ben böyle bakmak için istiyorum:

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 
Sadece katılmak ve çekerseniz

veriler aşağıdaki gibi görünecektir

Geçmişte, verilerimde ihtiyaç duyduğum tüm field_id'leri aramaya başvurdum ve her biri için CASE ifadeleri oluşturdum. Kullanıcıların kullandıkları uygulama, birden fazla ürün için veri içerir ve her ürün farklı alanlar içerir. Desteklenen ürün sayısı ve her bir ürün için alan sayısı göz önünde bulundurulduğunda (yukarıda gösterdiğim temel örneklerden çok daha fazlası), onları aramak ve CASE ifadelerinin büyük parçalarını yazmak uzun zaman alır.

Field_ids'e bakıp bir şeyler yazmasına gerek kalmadan ihtiyacım olanı elde etmek için orada bir hile kodu var mı diye merak ediyordum. PIVOT fonksiyonunun muhtemelen aradığım şey olduğunu biliyorum, ancak doğru şekilde çalışmasını sağlayamıyorum.

Yardım edebilir misiniz?

cevap

29

Sen sütunlar halinde veri Satırlarınızı dönüştürmek için PIVOT işlevini kullanabilirsiniz deneyin.

Orijinal sorgunuz tüm verileri almak için kullanılabilir, yalnızca benim yaptığım değişiklik, b.field_id sütununu hariç tutmak olabilir çünkü sonuç, sonucun son görüntüsünü değiştirir.

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; 

SQL Fiddle with Demo Bkz: Eğer sütunlara dönüştürmek istediğiniz field_name değerlerin, bilinen bir listesi varsa

sonra koda Sorgunuzla can. Eğer field_name için değerlerin bilinmeyen sayıda sahip olacak eğer

Ama, o zaman sonuç almak için dinamik SQL uygulamak gerekir:

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; 

bakınız.

| 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

Bu tam ihtiyacım budur.Seni reddetmek için bir temsilcim yok, ama buralarda başka biri bunu görüyorsa, lütfen bana destek olun! –

3

bu

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 cevabı benim için doğru biriydi ama sütun listesinde ayrı gerekli:: bunlar bu ikisi bir sonuç verecektir

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;