PIVOT в sql 2005 - PullRequest
       18

PIVOT в sql 2005

7 голосов
/ 13 октября 2008

Мне нужно повернуть один столбец (столбец чисел). Пример нужны эти данные:

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

выглядит так

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

любая помощь будет принята с благодарностью ...

Ответы [ 5 ]

12 голосов
/ 14 октября 2008

Использование ROW_NUMBER(), PIVOT и некоторого динамического SQL (но курсор не требуется):

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)
1 голос
/ 14 октября 2008

Только потому, что я хотел получить больше опыта с CTE, я придумал следующее:

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

Возможно, потребуется некоторая настройка, но это сработало на вашем примере

1 голос
/ 14 октября 2008

Здесь также можно использовать функцию объединения, аналогично другим вопросам, которые задавались о конкатенации данных.

Как создать функцию SQL Server для "объединения" нескольких строк из подзапроса в одно поле с разделителями?

1 голос
/ 14 октября 2008

На этот связанный вопрос должен быть необходим ответ: SQL Server: примеры данных PIVOTing String

Элемент управления Matrix в SSRS имеет динамические столбцы, если эти данные в любом случае связаны с отчетом, вы можете использовать его. В противном случае вам придется создать sproc sql, который динамически генерирует sql, как в exaamples, а затем выполняет его.

0 голосов
/ 14 октября 2008

Я не уверен, что то, что вы делаете, действительно возможно (или, по крайней мере, практично) в SQL - я не уверен, потому что я все еще не совсем уверен, что вы хотите сделать.

Вы можете создать эту сводную таблицу в своем клиентском приложении, например, с помощью:

select distinct Letter from MyTable

, чтобы получить список букв, а затем использовать параметризованный запрос внутри цикла:

select Number from MyTable where Letter=:letter

чтобы получить список цифр для каждой буквы.

...