Транспонирование таблицы в SQL-сервере - PullRequest
2 голосов
/ 08 декабря 2011

Я использую SQL Server 2005 для своего приложения.В моей хранимой процедуре есть таблица, в которой есть два столбца: C1 и C2.Я хочу транспонировать эту таблицу так, чтобы значения столбца C1 становились столбцами.Перед транспонированием (Таблица 1):

C1  C2
M1  U1
M1  U2
M1  U3
M2  U4
M2  U5

После транспонирования (Таблица 2):

M1  M2
U1  U4
U2  U5
U3  NULL

В Таблице 1 количество различных значений (M1, M2) может варьироваться.Таким образом, столбцы в таблице 2 не являются фиксированными.

Пожалуйста, предоставьте решение для достижения того же.

Ответы [ 3 ]

2 голосов
/ 14 января 2013

Для этого типа преобразования данных вы захотите использовать функцию PIVOT, которая доступна в SQL Server 2005+.Существует два способа применения функции pivot .

Если вы знаете значения заранее, то вы можете жестко закодировать значения в запросе.Аналогично этому:

select M1, M2
from
(
  select c1, c2,
    row_number() over(partition by c1 order by c1, c2) rn
  from yourtable
) src
pivot
(
  max(c2)
  for c1 in (M1, M2)
) piv

См. Скрипка SQL с демонстрацией .

Но если у вас есть неизвестное количество значений, которые вы хотите транспонировать в столбцы, тогда выможет использовать динамический SQL для создания запроса во время выполнения.

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(C1) 
                    from yourtable
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT ' + @cols + ' from 
             (
                select C1, C2,
                  row_number() over(partition by c1 order by c1, c2) rn
                from yourtable
            ) x
            pivot 
            (
                max(C2)
                for C1 in (' + @cols + ')
            ) p '

execute(@query)

См. SQL Fiddle с демоверсией .

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

| M1 |     M2 |
---------------
| U1 |     U4 |
| U2 |     U5 |
| U3 | (null) |
0 голосов
/ 13 декабря 2011

Это не точный результат, который вы хотите, но вы можете попробовать это

;WITH TAB1 AS
( SELECT  [ResponsibleID] C1,[ActionID] C2,1 ORD
  FROM [TEST].[dbo].[yourtable]
  WHERE 1=1
  )


 SELECT 
    CASE WHEN M1=1 THEN ActionID ELSE NULL END M1,
    CASE WHEN M2=1 THEN ActionID ELSE NULL END M2 
 FROM TAB1
 PIVOT(AVG(ORD) FOR RESPONSIBLEID IN ([M1],[M2])) AS ABC
0 голосов
/ 08 декабря 2011

Это, вероятно, тот случай, когда динамический sql ваш друг.Предполагая, что ваша базовая таблица называется «Транспонировать»:

--Get a Unique List of values from C1 --> These will be our column headers
DECLARE @Unique TABLE (C1 VARCHAR(25), fUsed BIT DEFAULT 0);
INSERT INTO @Unique (C1) SELECT DISTINCT C1 FROM Transpose;

DECLARE @TransSQL NVARCHAR(4000);
DECLARE @ColID NVARCHAR(25);

SET @TransSQL = N'SELECT ' 

--Loop over unique C1 values and construct the select statement
SELECT @ColID = (SELECT TOP 1 C1 FROM @Unique WHERE fUSed = 0);
WHILE @@ROWCOUNT <> 0 AND @ColID IS NOT NULL
BEGIN
    SET @TransSQL = @TransSQL + 'CASE C1 WHEN ' + '''' + @ColID + '''' + ' THEN C2 ELSE NULL END AS ' + @ColID + ', '

    --Update flag in table so we don't use this field again
    UPDATE u SET fUsed = 1 FROM @Unique u WHERE C1 = @ColID;
    SELECT @ColID = (SELECT TOP 1 C1 FROM @Unique WHERE fUSed = 0);
END

--Remove Trailing comma and add FROM clause
DECLARE @SQL NVARCHAR(4000)
SET @SQL = LEFT(@TransSQL,LEN(@TransSQL) -1) + ' FROM Transpose'

--For debugging purposes
PRINT @SQL;

--Execute the dynamic sql
EXEC sp_executesql @SQL;

Это не даст точную структуру, описанную вашим вопросом, потому что они не являются ключевым полем для группировки результатов.Вместо этого выходные данные будут выглядеть следующим образом:

M1     M2      M3
U1     NULL    NULL
U2     NULL    NULL
U3     NULL    NULL
NULL   U4      NULL
NULL   U5      NULL
NULL   NULL    U6

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...