2016-07-04 5 views
0

Я работаю с помощью функции Pivot, если можно «заполнить» данные, не включенные в основную таблицу. Моя таблица включает в себя следующие данные:SQL Pivot с неуравновешенными данными

create table tmpData (objID INT, colID varchar(5), value varchar(50)); 
insert into tmpData (objId, colId, value) values(21, 'col1', 'a value'); 
insert into tmpData (objId, colId, value) values(21, 'col2', 'col2_1'); 
insert into tmpData (objId, colId, value) values(21, 'col2', 'col2_2_x'); -- a second 'value' for col_2 
insert into tmpData (objId, colId, value) values(21, 'col3', 'col3_1'); 
insert into tmpData (objId, colId, value) values(22, 'col1', 'another value'); 
insert into tmpData (objId, colId, value) values(22, 'col2', 'col2_2'); 
insert into tmpData (objId, colId, value) values(22, 'col3', 'col3_2'); 

с функцией Pivot

select 
* 
from (
select 
    objID 
, colID 
, value 
from tmpData) 
t 
PIVOT (MAX(value) for colID in ([col1], [col2], [col3])) pivottable; 

я получаю только одно значение (макс) для ObjId = 21 в col2:

objID col1   col2   col3 
21 a value  col2_2_x  col3_1 
22 another value col2_2  col3_2 

Что мне нравится получить все значения И заполнить не заданные данные для objID = 21 в col1 и col3:

objID col1   col2  col3 
21 a value  col2_2  col3_1 
21 a value  col2_2_x col3_1 
22 another value col2_2  col3_2 

Возможно ли это с помощью функции Pivot или другим способом? Заранее благодарим Joerg

+0

Какие СУБД вы используете? Синтаксис выглядит как SQL Server. –

+0

в конце должен работать для SQL Server и ORACLE – DickerXXL

ответ

0

Вы, кажется, (хотите) хотите списки в столбцах. Если вы можете жить с этим результатом:

objID col1   col2  col3 
21 a value  col2_2  col3_1 
21 NULL   col2_2_x NULL 
22 another value col2_2  col3_2 

Затем вы можете сделать это путем перечисления значений:

select objId, 
     max(case when colId = 'col1' then value end) as col1, 
     max(case when colId = 'col2' then value end) as col2, 
     max(case when colId = 'col3' then value end) as col3 
from (select d.*, 
      dense_rank() over (partition by objId, colId order by (select NULL)) as seqnum 
     from tmpData d.* 
    ) t 
group by objId, seqnum; 

В SQL Server 2012+, вы можете делать то, что вы хотите с помощью кумулятивного max():

select objId, 
     max(max(case when colId = 'col1' then value end)) over (partition by objId order by seqnum) as col1, 
     max(max(case when colId = 'col2' then value end)) over (partition by objId order by seqnum) as col2, 
     max(max(case when colId = 'col3' then value end)) over (partition by objId order by seqnum) as col3 
from (select d.*, 
      dense_rank() over (partition by objId, colId order by (select value)) as seqnum 
     from tmpData d.* 
    ) t 
group by objId, seqnum; 

Обратите внимание, что order by в dense_rank() был изменен явно определить по значению.

+0

очень быстрый ответ. Благодарю. Второй SQL делает трюк для ORACLE :-). Вы знаете решение для SQL Server 2008? – DickerXXL

+0

Мне нравится обновлять это решение. Кумулятивный max() также работает для ORACLE. Но реальная жизнь сложнее, чем пример выше. В реальной жизни мне приходится иметь дело с более чем 100 столбцами, а не только 3. В этом случае ORACLE попадает в ORA-01467: слишком длинный ключ сортировки :-(Но хорошо, когда у вас не так много столбцов, он работает нормально – DickerXXL

+0

@DickerXXL ... При использовании 100 столбцов для сортировки кажется подозрительным. –

0

Использование CTE и слева присоединиться, чтобы получить значения из col1 и col3 для всех Col2 значений

;with 
t as (select distinct objID from #tmpData), 
t1 as (select objID, value col1 from #tmpData where colID = 'col1'), 
t2 as (select objID, value col2 from #tmpData where colID = 'col2'), 
t3 as (select objID, value col3 from #tmpData where colID = 'col3') 
select t.objID, col1, col2, col3 
from t 
left join t1 on t.objID = t1.objID 
left join t2 on t.objID = t2.objID 
left join t3 on t.objID = t3.objID 
order by t.objID 

это будет работать также, если у вас есть больше значения для col1 или col3

+1

Мне нравится обновлять это решение. «Self join» работает и для ORACLE, но реальная жизнь сложнее, чем пример выше. в реальной жизни мне приходится иметь дело с более чем 100 столбцами, а не только 3. В этом случае ORACLE потребляет> 100 ГБ временного табличного пространства и не заканчивается в результате через часы :-(Но хорошо, как только вы этого не сделаете много столбцов он работает нормально. – DickerXXL

+0

@ DickerXXL вы можете дать нам порядок величин записей, столбцов и отдельных objID? – MtwStark

Смежные вопросы