2010-09-15 21 views
8

Tôi có dữ liệuLàm thế nào để thiết kế Query để tạo cột động từ hàng

Table1

ID  Name 
----------- 
1  n1 
2  n2 
3  n4 

Table2

FID YearS Val 
---------------------- 
1  2008  Up 
1  2009  Down 
1  2010  Up 
2  2000  Up 
2  2001  Down 
2  2002  Up 
2  2003  Up 
3  2009  Down 
3  2010  Up 

Tôi muốn trả lại dữ liệu ở định dạng sau:

ID Yr1 Val1 Yr2 Val2 Yr3 Val3 Yr4 Val4 
-------------------------------------------------------- 
1 2008 Up  2009 Down 2010 Up  NULL Null 
2 2000 Up  2001 Down 2002 Up  2003 Up 
3 2009 Down 2010 Up NULL NULL NULL Null 

Dựa trên mức tối đa không có cột cho ID tôi muốn tạo tên cột và sau đó chuyển đổi hàng trong cột. Điều này có thể thực hiện bằng cách sử dụng truy vấn sql không?

+0

Sử dụng Trình tạo báo cáo để tạo báo cáo! –

+0

có lý do tại sao bạn sẽ có hai cột mỗi năm thay vì có năm tên cột? theo cách đó tất cả các năm của bạn được nhóm lại. – DForck42

Trả lời

1

Truy vấn này sẽ giúp

;WITH cte AS 
    (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY FID ORDER BY FID, YearS) AS NUMBER 
    FROM Table2 
    ) 

SELECT t.ID, MAX(CASE WHEN cte.number = 1 THEN cte.YearS END) as yr1, MAX(CASE WHEN cte.number = 1 THEN cte.Val END) as val1, 
MAX(CASE WHEN cte.number = 2 THEN cte.YearS END) as yr2, MAX(CASE WHEN cte.number = 2 THEN cte.Val END) as val2, 
MAX(CASE WHEN cte.number = 3 THEN cte.YearS END) as yr3, MAX(CASE WHEN cte.number = 3 THEN cte.Val END) as val3, 
MAX(CASE WHEN cte.number = 4 THEN cte.YearS END) as yr4, MAX(CASE WHEN cte.number = 4 THEN cte.Val END) as val4 
FROM Table1 T 
JOIN cte ON t.ID = cte.FID 
GROUP BY t.ID 
+0

có nhưng tôi không chắc chắn bao nhiêu năm sẽ có, cột của tôi có thể mở rộng vượt ra ngoài năm 4 như yr5, yr6, yr7 –

+0

Không giống như các hàng, bạn phải có một số cột được xác định trong mệnh đề SELECT (Tôi sẽ không đề cập đến SQL động ở đây).Bạn có thể thêm nhiều cột hơn vào truy vấn này, sẽ tạo ra tất cả các giá trị NULL khi các năm không tồn tại. – bobs

5

Tôi đã tạo ra một bảng gọi là "Table2", có chứa các dữ liệu bạn đã trình bày ở trên dưới tiêu đề Bảng 2 của bạn.

Đây là SQL tôi được sử dụng trong SQL Server 2008.

WITH RankedValues AS 
(
    SELECT 
     FID AS ID, 
     YearS, 
     ROW_NUMBER() OVER(PARTITION BY FID ORDER BY YearS) AS YearSRank, 
     Val 
    FROM 
     Table2 
) 
SELECT 
    ID, 
    MAX((CASE WHEN YearSRank = 1 THEN YearS ELSE 0 END)) AS Yr1, 
    MAX((CASE WHEN YearSRank = 1 THEN Val ELSE '' END)) AS Val1, 
    MAX((CASE WHEN YearSRank = 2 THEN YearS ELSE 0 END)) AS Yr2, 
    MAX((CASE WHEN YearSRank = 2 THEN Val ELSE '' END)) AS Val2, 
    MAX((CASE WHEN YearSRank = 3 THEN YearS ELSE 0 END)) AS Yr3, 
    MAX((CASE WHEN YearSRank = 3 THEN Val ELSE '' END)) AS Val3, 
    MAX((CASE WHEN YearSRank = 4 THEN YearS ELSE 0 END)) AS Yr4, 
    MAX((CASE WHEN YearSRank = 4 THEN Val ELSE '' END)) AS Val4 
FROM 
    RankedValues 
GROUP BY 
    ID 

Trên SQL sẽ cho kết quả này:

ID Yr1  Val1 Yr2  Val2 Yr3  Val3 Yr4  Val4 
--------------------------------------------------------------------- 
1 2008 Up 2009 Down 2010 Up 0  
2 2000 Up 2001 Down 2002 Up 2003 Up 
3 2009 Down 2010 Up  0    0  

Lý do bạn không thấy NULL giá trị là vì ELSE trong mỗi câu hỏi CASE. Nếu bạn muốn có giá trị NULL, chỉ cần xóa ELSE 0ELSE '' theo yêu cầu.

Tôi không biết tại thời điểm này nếu có thể thực hiện điều này, ví dụ: xử lý số lượng FID không xác định, điều này cũng có nghĩa là tạo tên cột (Yr1, al1, Yr2, v.v.) nói chung.

Bạn có thể có thể đạt được điều này với SQL động nhưng vì tôi không phải là một fan hâm mộ lớn của SQL động, tôi sẽ thử và xem xét một cách khác để giải quyết vấn đề đó.

- Chỉnh sửa (Added trục cách tiếp cận để completness) -

Tôi nhìn vào liên kết Joe Stefanelli đăng và tôi được thêm vào SQL dưới đây để biết yêu cầu của bạn. Mặc dù tôi không thích ý tưởng về SQL động nhưng tôi không thể tìm thấy bất kỳ cách nào khác trong trường hợp cụ thể này.

DECLARE @query VARCHAR(4000) 
DECLARE @years VARCHAR(2000) 

SELECT @years = STUFF((
    SELECT DISTINCT 
     '],[' + ltrim(str(YearS)) 
    FROM Table2 
    ORDER BY '],[' + ltrim(str(YearS)) 
    FOR XML PATH('')), 1, 2, '') + ']' 

SET @query = 
    'SELECT * FROM 
    (
     SELECT FID AS ID,YearS,Val 
     FROM Table2 
    ) AS t 
    PIVOT (MAX(Val) FOR YearS IN (' + @years + ')) AS pvt' 

EXECUTE (@query) 

này sẽ dẫn đến việc follwing:

ID 2000 2001 2002 2003 2008 2009 2010 
--------------------------------------------------------- 
1 NULL NULL NULL NULL Up  Down Up 
2 Up  Down Up  Up  NULL NULL NULL 
3 NULL NULL NULL NULL NULL Down Up 

Tùy thuộc định dạng và tiếp cận bạn thích nhất, ít nhất bạn có các tùy chọn của bạn lót ra.

+0

Tôi chưa thấy câu trả lời của bob trong khi tôi đang làm việc với tôi. Điều tương tự về cơ bản. Không có nghĩa là nhân đôi câu trả lời. – Nope

Các vấn đề liên quan