2014-02-11 4 views
13

У меня есть таблица с большой базой данных, на которой мне нужно выполнить динамическое действие с использованием Microsoft SQL Server.Объединить несколько строк в несколько столбцов динамически в SQL Server

Из результата, например так:

badge | name | Job | KDA | Match 
- - - - - - - - - - - - - - - - 
T996 | Darrien | AP | 3.0 | 20 
T996 | Darrien | ADC | 2.8 | 16 
T996 | Darrien | TOP | 5.0 | 120 

В результате, как это с помощью SQL:

badge | name | AP_KDA | AP_Match | ADC_KDA | ADC_Match | TOP_KDA | TOP_Match 
- - - - - - - - - 
T996 | Darrien | 3.0 | 20  | 2.8 | 16  | 5.0 | 120  

Даже если есть 30 строк, она также будет совмещать в один ряд с 60 столбцов ,

В настоящее время я могу сделать это с помощью жесткого кодирования (см. Пример ниже), но не динамически.

Select badge,name, 
(
SELECT max(KDA) 
FROM table 
WHERE (h.badge = badge) AND (h.name = name) 
AND (Job = 'AP') 
) AP_KDA, 
(
SELECT max(Match) 
FROM table 
WHERE (h.badge = badge) AND (h.name = name) 
AND (Job = 'AP') 
) AP_Match, 
(
SELECT max(KDA) 
FROM table 
WHERE (h.badge = badge) AND (h.name = name) 
AND (Job = 'ADC') 
) ADC_KDA, 
(
SELECT max(Match) 
FROM table 
WHERE (h.badge = badge) AND (h.name = name) 
AND (Job = 'ADC') 
) ADC_Match, 
(
SELECT max(KDA) 
FROM table 
WHERE (h.badge = badge) AND (h.name = name) 
AND (Job = 'TOP') 
) TOP_KDA, 
(
SELECT max(Match) 
FROM table 
WHERE (h.badge = badge) AND (h.name = name) 
AND (Job = 'TOP') 
) TOP_Match 
from table h 

Мне нужен оператор MSSQL, который позволяет мне комбинировать несколько строк в одну строку. Содержимое колонки 3 (Job) будет сочетаться с заголовками столбцов 4 и 5 (KDA и Match) и стать новой колонкой.

Так что, если есть 6 различных значений для Job (скажем Job1 через Job6), то результат будет иметь 12 столбцов, например .: Job1_KDA, Job1_Match, Job2_KDA, Job2_Match и т.д., сгруппированных по значком и названием.

Мне нужна инструкция, которая может проходить через данные столбца 3, поэтому мне не нужно жестко кодировать (повторить запрос для каждого возможного значения Job) или использовать временную таблицу.

+0

Привет всем, вопрос, который я задаю, представляет собой инструкцию mssql, которая позволяет мне комбинировать несколько строк в одну строку. Содержимое столбца 3 будет объединено с заголовком столбца 4,5 и станет новым столбцом. Поэтому, если в столбце 3 имеется 6 различных данных, тогда будет создано 12 столбцов. например: Job1_KDA, Job1_Match, Job2_KDA, Job2_Match, Job3_KDA, Job3_Match, Job4_KDA, Job4_Match – chabu

+1

Здесь есть много связанных вопросов. Найдите '[sql-server] pivot' для нескольких примеров выполнения именно того, что вы просите. Например, [этот вопрос] (http://stackoverflow.com/q/24470/62576) выполняет операцию аналогичного типа (хотя он преобразует шесть строк в три). –

ответ

10

Я хотел бы сделать это с помощью динамического SQL, но это (http://sqlfiddle.com/#!6/a63a6/1/0) решение PIVOT:

SELECT badge, name, [AP_KDa], [AP_Match], [ADC_KDA],[ADC_Match],[TOP_KDA],[TOP_Match] FROM 
(
SELECT badge, name, col, val FROM(
SELECT *, Job+'_KDA' as Col, KDA as Val FROM @T 
UNION 
SELECT *, Job+'_Match' as Col,Match as Val FROM @T 
) t 
) tt 
PIVOT (max(val) for Col in ([AP_KDa], [AP_Match], [ADC_KDA],[ADC_Match],[TOP_KDA],[TOP_Match])) AS pvt 

Bonus: Это как PIVOT может быть объединено с динамическим SQL (http://sqlfiddle.com/#!6/a63a6/7/0), опять-таки я предпочел бы сделать это проще, без PIVOT, но это только хорошо упражнения для меня:

SELECT badge, name, cast(Job+'_KDA' as nvarchar(128)) as Col, KDA as Val INTO #Temp1 FROM Temp 
INSERT INTO #Temp1 SELECT badge, name, Job+'_Match' as Col, Match as Val FROM Temp 

DECLARE @columns nvarchar(max) 
SELECT @columns = COALESCE(@columns + ', ', '') + Col FROM #Temp1 GROUP BY Col 

DECLARE @sql nvarchar(max) = 'SELECT badge, name, '[email protected]+' FROM #Temp1 PIVOT (max(val) for Col in ('[email protected]+')) AS pvt' 
exec (@sql) 

DROP TABLE #Temp1 
+0

Привет, Роман, спасибо за предложение решения. Но это не решило мое дело, так как мне нужно имя столбца, чтобы динамически создавать себя, а не жестко кодировать его. Как я могу сделать инструкцию PIVOT не статической переменной, как AP_KDA, AP_Match, но что-то вроде Job + '_ KDA', Job + '_ Match'? – chabu

+0

Я думал, что дал вам ответ, говорящий «using dynamic sql». Вам нужна помощь для написания динамического запроса? PIVOT был разгневан мной только потому, что я редко их использовал, и это было интересно для меня. –

+0

Кажется, все в порядке, но я получаю сообщение об ошибке на последней строке. DECLARE @sql nvarchar (max) = 'Значок SELECT, имя,' + @ columns + 'FROM # Temp1 PIVOT (max (val) для Col in (' + @ columns + ')) AS pvt' Это дает мне эту ошибку , Msg 139, Level 15, State 1, Line 0 Невозможно присвоить значение по умолчанию локальной переменной. Msg 137, уровень 15, состояние 2, строка 6 Должен объявить скалярную переменную «@sql». Я искал решение проблемы, все пользователи также упоминают необходимость преобразования столбцов в nvarchar, поэтому я сделал это. Я уже преобразовал все столбцы в nvarchar, но все еще не смог решить эту ошибку. – chabu

1

Объединение нескольких строк и столбцов в строки и группы по ID

IF OBJECT_ID('usr_CUSTOMER') IS NOT NULL 
DROP TABLE usr_CUSTOMER 

--------------------------CRATE TABLE--------------------------------------------------- 

GO 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE TABLE [dbo].[usr_CUSTOMER](
    [Last_Name] [nvarchar](50) NULL, 
    [First_Name] [nvarchar](50) NULL, 
    [Middle_Name] [nvarchar](50) NOT NULL, 
    [ID] [int] NULL 
) ON [PRIMARY] 


GO 
INSERT [dbo].[usr_CUSTOMER] ([Last_Name], [First_Name], [Middle_Name], [ID]) VALUES (N'gal', N'ornon', N'gili', 111) 
GO 
INSERT [dbo].[usr_CUSTOMER] ([Last_Name], [First_Name], [Middle_Name], [ID]) VALUES (N'porat', N'Yahel', N'LILl', 44444) 
GO 
INSERT [dbo].[usr_CUSTOMER] ([Last_Name], [First_Name], [Middle_Name], [ID]) VALUES (N'Shabtai', N'Or', N'Orya', 2222) 
GO 
INSERT [dbo].[usr_CUSTOMER] ([Last_Name], [First_Name], [Middle_Name], [ID]) VALUES (N'alex', N'levi', N'dolev', 33) 
GO 
INSERT [dbo].[usr_CUSTOMER] ([Last_Name], [First_Name], [Middle_Name], [ID]) VALUES (N'oren', N'cohen', N'ornini', 44444) 
GO 
INSERT [dbo].[usr_CUSTOMER] ([Last_Name], [First_Name], [Middle_Name], [ID]) VALUES (N'ron', N'ziyon', N'amir', 2222) 
GO 



----------------------------script--------------------------------------------- 

IF OBJECT_ID('tempdb..#TempString') IS NOT NULL 
DROP TABLE #TempString 

IF OBJECT_ID('tempdb..#tempcount') IS NOT NULL 
DROP TABLE #tempcount 

IF OBJECT_ID('tempdb..#tempcmbnition') IS NOT NULL 
     DROP TABLE #tempcmbnition 
-------------------------------------------------------------------------------- 
-------------------------------------------------------------------------------- 

SELECT ID, 
    [Last_Name] + '#' + [First_Name] + '#' + ISNULL([Middle_Name], '') as StringRow 
    INTO #TempString 
FROM [dbo].[usr_CUSTOMER] 
ORDER BY StringRow 


select distinct id 
into #tempcount 
from usr_CUSTOMER 


CREATE TABLE [dbo].[#tempcmbnition](
     [ID] [int] NULL, 
     [combinedString] [nvarchar](max) NULL 
) 

-------------------------------------------------------------------------------- 
-------------------------------------------------------------------------------- 

DECLARE @tableID table(ID int) 
insert into @tableID(ID) (select distinct Id from #tempcount) 

DECLARE @CNT int 
SET @CNT = (select count(*) from @tableID) 


declare @lastRow int 
-------------------------------------------------------------------------------- 
-------------------------------------------------------------------------------- 


WHILE (@CNT >=1) 
    BEGIN  

     SET @lastRow = (SELECT TOP 1 id FROM #tempcount ORDER BY id DESC) 
     DECLARE @combinedString VARCHAR(MAX) 
     set @combinedString = '' 
     SELECT @combinedString = COALESCE(@combinedString + '^ ', '') + StringRow 
     from #TempString 
     where ID = @lastRow 
     insert into #tempcmbnition (ID, [combinedString]) values(@lastRow ,@combinedString) 
     SET @CNT = @CNT-1 
     DELETE #tempcount where ID = @lastRow 
    END 
-------------------------------------------------------------------------------- 
-------------------------------------------------------------------------------- 
-- if you what remove first char 
-- UPDATE #tempcmbnition 
-- SET combinedString = RIGHT(combinedString, LEN(combinedString) - 1) 
-------------------------------------------------------------------------------- 
-------------------------------------------------------------------------------- 

select *from #TempString 
select * from #tempcmbnition 
Смежные вопросы