2013-08-08 70 views
13

Tôi xin lỗi vì đã gửi một câu hỏi khác về chủ đề này, nhưng tôi đã đọc qua nhiều câu trả lời về vấn đề này và dường như tôi không thể làm cho nó hoạt động được.SQL Server 2008 Dữ liệu dọc sang ngang

Tôi có ba bảng tôi cần tham gia và kéo thông tin. Một trong các bảng chỉ có 3 cột và lưu trữ dữ liệu theo chiều dọc. Tôi muốn chuyển dữ liệu đó sang định dạng ngang.

Các dữ liệu sẽ trông như thế này nếu tôi chỉ cần tham gia và kéo:

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) 

Kết quả:

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 

Thay vào đó, tôi muốn nó trông như thế này:

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 

Trong quá khứ, tôi chỉ cần sử dụng để tìm kiếm tất cả các field_id của tôi cần thiết trong dữ liệu của tôi và tạo ra các báo cáo CASE cho mỗi một. Ứng dụng mà người dùng đang sử dụng chứa dữ liệu cho nhiều sản phẩm và mỗi sản phẩm chứa các trường khác nhau. Xem xét số lượng sản phẩm được hỗ trợ và số lượng trường cho mỗi sản phẩm (nhiều, nhiều hơn ví dụ cơ bản tôi đã trình bày ở trên) phải mất một thời gian dài để tìm kiếm chúng và viết ra các khối lượng lớn các báo cáo CASE.

Tôi đã tự hỏi nếu có một số mã lừa đảo ở đó để đạt được những gì tôi cần mà không cần phải tìm kiếm các field_ids và viết ra. Tôi biết chức năng PIVOT có thể là những gì tôi đang tìm kiếm, tuy nhiên, tôi dường như không thể làm cho nó hoạt động chính xác.

Hãy suy nghĩ các bạn có thể giúp đỡ?

Trả lời

29

Bạn có thể sử dụng PIVOT chức năng để chuyển đổi hàng dữ liệu của bạn thành các cột.

Truy vấn ban đầu của bạn có thể được sử dụng để truy xuất tất cả dữ liệu, thay đổi duy nhất tôi thực hiện để loại trừ cột b.field_id vì điều này sẽ thay đổi hiển thị kết quả cuối cùng.

Nếu bạn có một danh tiếng của field_name giá trị mà bạn muốn chuyển thành cột, sau đó bạn có thể mã hóa cứng truy vấn của bạn:

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; 

Xem SQL Fiddle with Demo.

Nhưng nếu bạn đang đi để có một số không rõ các giá trị cho field_name, sau đó bạn sẽ cần phải thực hiện SQL động để có được kết quả:

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; 

Xem . Cả hai điều này sẽ cho kết quả là: Câu trả lời

| 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

Đây chính là những gì tôi cần.Tôi không có đại diện để đưa bạn lên, nhưng nếu có ai khác ở đây thấy điều này, xin vui lòng upvote cho tôi! –

3

Hãy thử điều này

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 là một trong những phù hợp với tôi, nhưng tôi cần riêng biệt trong danh sách cột:

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; 
Các vấn đề liên quan