2010-09-15 11 views
8

Mam daneJak zaprojektować do tworzenia dynamicznych kolumn z rzędami Query

Tabela1

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

Tabela 2

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 

chcę wrócić dane w następującym formacie:

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 

Na podstawie maksimum liczba kolumn dla identyfikatora Chcę utworzyć nazwy kolumn, a następnie konwertować wiersze w kolumnach. Czy jest to możliwe przy użyciu kwerendy sql?

+0

Skorzystaj z programu Report Builder do tworzenia raportów! –

+0

czy istnieje powód, dla którego miałbyś mieć dwie kolumny rocznie zamiast na rok podać nazwę kolumny? w ten sposób wszystkie twoje lata są pogrupowane. – DForck42

Odpowiedz

1

To zapytanie powinno pomóc

;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

Tak, ale nie jestem pewien, ile lat będzie tam, moje kolumny mogą wykraczać poza yr4 jak yr5, yr6, yr7 –

+0

W przeciwieństwie do wierszy, musisz mieć określoną liczbę kolumn w klauzuli SELECT (nie będę wspominać dynamiczny SQL tutaj).Możesz dodać więcej kolumn do tego zapytania, które wygenerują wszystkie wartości NULL, gdy te lata nie istnieją. – bobs

5

Stworzyłem tabelę o nazwie „Tabela 2”, zawierające dane, które zostały pokazane powyżej pod nagłówkiem tabeli 2.

Oto SQL użyłem w 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 

Powyższy SQL spowoduje to:

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  

Powodem nie widać NULL wartości jest ze względu na ELSE w każdym oświadczeniu CASE. Jeśli wolisz mieć wartości NULL, usuń po prostu ELSE 0 i ELSE '' zgodnie z wymaganiami.

Nie wiem w tej chwili, czy jest możliwe wykonanie tego rodzaju, np .: przetwarzanie nieznanej ilości różnych FID, ponieważ oznaczałoby to również generowanie nazw kolumn (Yr1, al1, Yr2 itd.) ogólnie.

Można to osiągnąć dzięki dynamicznemu SQL, ale ponieważ nie jestem wielkim fanem dynamicznego SQL, spróbowałbym zbadać inny sposób radzenia sobie z tym.

- Edycja (podejście Dodany pivot dla kompletności) -

Spojrzałem na link Joe Stefanelli pisał i dodałem SQL poniżej dla Państwa wymagań. Chociaż nie podoba mi się idea dynamicznego SQL, nie mogłem znaleźć żadnego innego sposobu w tym konkretnym przypadku.

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) 

Spowoduje to 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 

zależności w jakim formacie i podejście lubisz najbardziej, przynajmniej masz opcje wyłożone na zewnątrz.

+0

Nie widziałem odpowiedzi bobslejek podczas pracy nad moim. Zasadniczo to samo. Nie chciał duplikować odpowiedzi. – Nope

Powiązane problemy