The following is a solution based on a dynamic query adapted to the data itself, you can use PIVOT
but we still have the problem of not wanting to "write" all levels of transposition, so we should always go through a dynamic consultation. This type of queries has its associated problems, lack of engine optimization, security problems, and a limit on the size of the sentence in NVARCHAR(MAX)
, for what you are looking for it will surely help you.
First of all we must transform your variable type table to a physical table even if it is temporary so that the execution with sp_executesql
can "see" the table. I also added a third level just to test.
SET NOCOUNT ON
CREATE TABLE #TEMP_INC (
INC_ID INT,
OBJ_ID INT,
INC_DESCRIPCION VARCHAR(255),
INC_TIPOOBJ INT,
INC_FC DATE,
INC_FM DATE,
INA_ID INT,
NUM INT
)
INSERT INTO #TEMP_INC (INC_ID, OBJ_ID, INC_DESCRIPCION, INC_TIPOOBJ, INC_FC, INC_FM, INA_ID)
VALUES
(1439166, 620310, '* descripcion tipo 123', 7, '2015-07-04 17:07:36.000', '2015-07-04 17:07:36.000', 8),
(1439167, 620310, '* descripcion tipo 124', 7, '2015-07-04 17:07:36.000', '2015-07-04 17:07:36.000', 8),
(1439168, 620311, '* descripcion tipo 125', 7, '2015-07-04 17:07:37.000', '2015-07-04 17:07:37.000', 12),
(1439169, 620311, '* descripcion tipo 126', 7, '2015-07-04 17:07:37.000', '2015-07-04 17:07:37.000', 15),
(1439170, 620312, '* descripcion tipo 127', 7, '2015-07-04 17:07:37.000', '2015-07-04 17:07:37.000', 20),
(1439171, 620312, '* descripcion tipo 128', 7, '2015-07-04 17:07:37.000', '2015-07-04 17:07:37.000', 22),
(1439172, 620313, '* descripcion tipo 129', 7, '2015-07-04 17:07:38.000', '2015-07-04 17:07:38.000', 27),
(1439173, 620313, '* descripcion tipo 132', 7, '2015-07-04 17:07:38.000', '2015-07-04 17:07:38.000', 26),
(1439174, 620314, '* descripcion tipo 133', 7, '2015-07-04 17:07:39.000', '2015-07-04 17:07:39.000', 26),
(1439175, 620314, '* descripcion tipo 134', 7, '2015-07-04 17:07:39.000', '2015-07-04 17:07:39.000', 24),
(1439176, 620314, '* descripcion tipo 135', 7, '2015-07-04 17:07:39.000', '2015-07-04 17:07:40.000', 25)
-- Obtengo el máximo nivel de apertura
DECLARE @MaxLevels INT
SELECT @MaxLevels = MAX(Cantidad)
FROM (SELECT COUNT(DISTINCT INC_ID) AS 'Cantidad'
FROM #TEMP_INC
GROUP BY OBJ_ID
) c
UPDATE #TEMP_INC
SET NUM = N.NUM
FROM #TEMP_INC T
INNER JOIN (SELECT INC_ID, ROW_NUMBER() OVER (PARTITION BY OBJ_ID ORDER BY OBJ_ID, INC_ID) AS NUM
FROM #TEMP_INC
) N
ON N.INC_ID = T.INC_ID
DECLARE @SQL NVARCHAR(MAX)
SELECT @SQL = 'SELECT' + CHAR(13)
SELECT @SQL = @SQL +'' +
' MAX(CASE WHEN NUM = ' + CONVERT(VARCHAR,N.NUM) + ' THEN INC_ID ELSE NULL END) AS ''INC_ID' + CONVERT(VARCHAR,N.NUM) + ''', ' + CHAR(13) +
' MAX(CASE WHEN NUM = ' + CONVERT(VARCHAR,N.NUM) + ' THEN OBJ_ID ELSE NULL END) AS ''OBJ_ID' + CONVERT(VARCHAR,N.NUM) + ''', ' + CHAR(13) +
' MAX(CASE WHEN NUM = ' + CONVERT(VARCHAR,N.NUM) + ' THEN INC_DESCRIPCION ELSE NULL END) AS ''INC_DESCRIPCION' + CONVERT(VARCHAR,N.NUM) + ''', ' + CHAR(13) +
' MAX(CASE WHEN NUM = ' + CONVERT(VARCHAR,N.NUM) + ' THEN INC_TIPOOBJ ELSE NULL END) AS ''INC_TIPOOBJ' + CONVERT(VARCHAR,N.NUM) + ''', ' + CHAR(13) +
' MAX(CASE WHEN NUM = ' + CONVERT(VARCHAR,N.NUM) + ' THEN INC_FC ELSE NULL END) AS ''INC_FC' + CONVERT(VARCHAR,N.NUM) + ''', ' + CHAR(13) +
' MAX(CASE WHEN NUM = ' + CONVERT(VARCHAR,N.NUM) + ' THEN INC_FM ELSE NULL END) AS ''INC_FM' + CONVERT(VARCHAR,N.NUM) + ''', ' + CHAR(13) +
' MAX(CASE WHEN NUM = ' + CONVERT(VARCHAR,N.NUM) + ' THEN INA_ID ELSE NULL END) AS ''INA_ID' + CONVERT(VARCHAR,N.NUM) + ''', ' + CHAR(13) +
''
FROM ( SELECT ROW_NUMBER() OVER (ORDER BY ID) AS NUM
FROM SYSCOLUMNS
) N
WHERE N.NUM <= @MaxLevels
SELECT @SQL = LEFT(@SQL, LEN(@SQL)- 3)
SELECT @SQL = @SQL + CHAR(13) +
' FROM #TEMP_INC' + CHAR(13) +
' GROUP BY OBJ_ID'
-- PRINT @SQL
SET NOCOUNT OFF
EXECUTE SP_EXECUTESQL @SQL
DROP TABLE #TEMP_INC
Explanation
We obtain the highest possible level of openness, that is, how many
columns * levels we are going to "transpose" ( @MaxLevels
)
We update a new field NUM
that numbers each new record of
OBJ_ID
and what we will use later
We generate the dynamic @SQL
by repeating each field by @MaxLevels
,
we use any table, in my case syscolumns
that has many
records to generate a sequence, obviously the amount of
records must be greater than @MaxLevels
We finish completing the sentence and execute it through
EXECUTE SP_EXECUTESQL @SQL
If you are curious about the final sentence, here is an example
SELECT
MAX(CASE WHEN NUM = 1 THEN INC_ID ELSE NULL END) AS 'INC_ID1',
MAX(CASE WHEN NUM = 1 THEN OBJ_ID ELSE NULL END) AS 'OBJ_ID1',
MAX(CASE WHEN NUM = 1 THEN INC_DESCRIPCION ELSE NULL END) AS 'INC_DESCRIPCION1',
MAX(CASE WHEN NUM = 1 THEN INC_TIPOOBJ ELSE NULL END) AS 'INC_TIPOOBJ1',
MAX(CASE WHEN NUM = 1 THEN INC_FC ELSE NULL END) AS 'INC_FC1',
MAX(CASE WHEN NUM = 1 THEN INC_FM ELSE NULL END) AS 'INC_FM1',
MAX(CASE WHEN NUM = 1 THEN INA_ID ELSE NULL END) AS 'INA_ID1',
MAX(CASE WHEN NUM = 2 THEN INC_ID ELSE NULL END) AS 'INC_ID2',
MAX(CASE WHEN NUM = 2 THEN OBJ_ID ELSE NULL END) AS 'OBJ_ID2',
MAX(CASE WHEN NUM = 2 THEN INC_DESCRIPCION ELSE NULL END) AS 'INC_DESCRIPCION2',
MAX(CASE WHEN NUM = 2 THEN INC_TIPOOBJ ELSE NULL END) AS 'INC_TIPOOBJ2',
MAX(CASE WHEN NUM = 2 THEN INC_FC ELSE NULL END) AS 'INC_FC2',
MAX(CASE WHEN NUM = 2 THEN INC_FM ELSE NULL END) AS 'INC_FM2',
MAX(CASE WHEN NUM = 2 THEN INA_ID ELSE NULL END) AS 'INA_ID2',
MAX(CASE WHEN NUM = 3 THEN INC_ID ELSE NULL END) AS 'INC_ID3',
MAX(CASE WHEN NUM = 3 THEN OBJ_ID ELSE NULL END) AS 'OBJ_ID3',
MAX(CASE WHEN NUM = 3 THEN INC_DESCRIPCION ELSE NULL END) AS 'INC_DESCRIPCION3',
MAX(CASE WHEN NUM = 3 THEN INC_TIPOOBJ ELSE NULL END) AS 'INC_TIPOOBJ3',
MAX(CASE WHEN NUM = 3 THEN INC_FC ELSE NULL END) AS 'INC_FC3',
MAX(CASE WHEN NUM = 3 THEN INC_FM ELSE NULL END) AS 'INC_FM3',
MAX(CASE WHEN NUM = 3 THEN INA_ID ELSE NULL END) AS 'INA_ID3'
FROM #TEMP_INC
GROUP BY OBJ_ID