2008-10-13 13 views
7

Muszę obrócić jedną kolumnę (kolumna Liczby). przykład trzeba te dane:PIVOT w sql 2005

a 1 
a 2 
b 3 
b 4 
c 5 
d 6 
d 7 
d 8 
d 9 
e 10 
e 11 
e 12 
e 13 
e 14 

wyglądać następująco

a 1 2 
b 3 4 
c 5 
d 6 7 8 9 
e 10 11 12 13 14 

każda pomoc będzie bardzo mile widziane ...

+0

Wygląda na to trzeba oczyścić formatowanie trochę. –

+0

Co rozumiesz przez "wyglądać tak" dokładnie? Czy chcesz wszystkie liczby dla wiersza w jednej kolumnie, oddzielone spacjami? – Blorgbeard

+0

dynamiczne kolumny lub pojedyncza kolumna z oddzielonymi przecinkami. – IZar

Odpowiedz

1

To pytanie związane powinny mieć odpowiedź, czego potrzebujesz: SQL Server: Examples of PIVOTing String data

Formant macierzy w usłudze SSRS ma dynamiczne kolumny, jeśli te dane są mimo wszystko związane z raportem, wtedy można go użyć. W przeciwnym razie będziesz musiał utworzyć sql sproc, który wygeneruje sql jak w przykładach dynamicznie, a następnie wykona go.

+0

BB dzięki za odpowiedź. ale to nie działa dla mnie. Potrzebuję dynamicznych kolumn. – IZar

+0

Możesz rozwiązać ten problem, używając dynamicznego SQL. Dynamiczny problem korzysta z dynamicznego SQL! :) (Zrobiłem to wcześniej z datami i działało dobrze.) – BoltBait

1

Tylko dlatego, że chciałem trochę więcej doświadczenia z CTE, wymyśliłem następujące:

WITH CTE(CTEstring, CTEids, CTElast_id) 
AS 
(
    SELECT string, CAST(id AS VARCHAR(1000)), id 
    FROM dbo.Test_Pivot TP1 
    WHERE NOT EXISTS (SELECT * FROM dbo.Test_Pivot TP2 WHERE TP2.string = TP1.string AND TP2.id < TP1.id) 
    UNION ALL 
    SELECT CTEstring, CAST(CTEids + ' ' + CAST(TP.id AS VARCHAR) AS VARCHAR(1000)), TP.id 
    FROM dbo.Test_Pivot TP 
    INNER JOIN CTE ON 
     CTE.CTEstring = TP.string 
    WHERE 
     TP.id > CTE.CTElast_id AND 
     NOT EXISTS (SELECT * FROM dbo.Test_Pivot WHERE string = CTE.CTEstring AND id > CTE.CTElast_id AND id < TP.id) 
) 
SELECT 
    t1.CTEstring, t1.CTEids 
FROM CTE t1 
INNER JOIN (SELECT CTEstring, MAX(LEN(CTEids)) AS max_len_ids FROM CTE GROUP BY CTEstring) SQ ON SQ.CTEstring = t1.CTEstring AND SQ.max_len_ids = LEN(t1.CTEids) 
ORDER BY CTEstring 
GO 

To może potrzebować trochę skomplikowany, ale to działało z przykładu

+0

Tom, Nie sądzę, że to zadziała, ponieważ każda grupa może mieć różną wartość. – IZar

+0

Nie widzę, jak to wpłynęłoby na rzeczy, chyba że długość struny przekroczył 1000, którą można obsłużyć, zwiększając jedynie rozmiar VARCHAR. CTE jest rekursywny, niezbyt ograniczony przez liczbę. –

0

nie jestem pewien, że to co robisz jest naprawdę możliwe (lub przynajmniej praktyczny) w SQL - nie jestem pewien, bo jeszcze nie jestem do końca pewien, co chcesz zrobić.

Można zbudować tę tabelę przestawną w aplikacji klienckiej, na przykład:

select distinct Letter from MyTable 

aby otrzymać listę liter, a następnie za pomocą zapytania parametrycznego wewnątrz pętli:

select Number from MyTable where Letter=:letter 

aby uzyskać listę numerów dla każdej litery.

11

Korzystanie ROW_NUMBER(), PIVOT a niektóre dynamiczny SQL (ale nie konieczne kursor):

CREATE TABLE [dbo].[stackoverflow_198716](
    [code] [varchar](1) NOT NULL, 
    [number] [int] NOT NULL 
) ON [PRIMARY] 

DECLARE @sql AS varchar(max) 
DECLARE @pivot_list AS varchar(max) -- Leave NULL for COALESCE technique 
DECLARE @select_list AS varchar(max) -- Leave NULL for COALESCE technique 

SELECT @pivot_list = COALESCE(@pivot_list + ', ', '') + '[' + CONVERT(varchar, PIVOT_CODE) + ']' 
     ,@select_list = COALESCE(@select_list + ', ', '') + '[' + CONVERT(varchar, PIVOT_CODE) + '] AS [col_' + CONVERT(varchar, PIVOT_CODE) + ']' 
FROM (
    SELECT DISTINCT PIVOT_CODE 
    FROM (
     SELECT code, number, ROW_NUMBER() OVER (PARTITION BY code ORDER BY number) AS PIVOT_CODE 
     FROM stackoverflow_198716 
    ) AS rows 
) AS PIVOT_CODES 

SET @sql = ' 
;WITH p AS (
    SELECT code, number, ROW_NUMBER() OVER (PARTITION BY code ORDER BY number) AS PIVOT_CODE 
    FROM stackoverflow_198716 
) 
SELECT code, ' + @select_list + ' 
FROM p 
PIVOT (
    MIN(number) 
    FOR PIVOT_CODE IN (
     ' + @pivot_list + ' 
    ) 
) AS pvt 
' 

PRINT @sql 

EXEC (@sql)