2013-08-09 2 views
0

мне нужны следующие данныестрочном смещение повернута данные

ID 1   2   3   4   5 
--- ------------ ------------ ------------ ------------ ----------- 
1 NULL   NULL   NULL   NULL   Level 1 
2 NULL   NULL   NULL   Level 1  Level 2 
3 NULL   NULL   Level 1  Level 2  Level 3 
4 NULL   Level 1  Level 2  Level 3  Level 4 
5 Level 1  Level 2  Level 3  Level 4  Level 5 

быть трансформированы как:

ID Level1  Level2  Level3  Level4  Level5 
--- ------------ ------------ ------------ ------------ ------------ 
1 Level 1  NULL   NULL   NULL   NULL 
2 Level 1  Level 2  NULL   NULL   NULL 
3 Level 1  Level 2  Level 3  NULL   NULL 
4 Level 1  Level 2  Level 3  Level 4  NULL 
5 Level 1  Level 2  Level 3  Level 4  Level 5 

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

данные происходят от автореферентной таблицы:

create table data (ID int not NULL, ParentID int, Name varchar(50)) 

, применяя следующее заявление (который обернут в функцию табличного значения) на подмножество записей из этой таблицы:

with Path(ID, ParentID, Name, Level) 
as 
(
    select ID, ParentID, Name, 0 from data where ID = @id 
    union all 
    select d.ID, d.ParentID, d.Name, p.Level-1 
    from data d 
     join Path p on p.ParentID = d.ID 
) 
select 
    [1], [2], [3], [4], [5] 
from 
    (select 5 + Level as Level, Name from Path) s 
    pivot (max(Name) for Level in ([1], [2], [3], [4], [5])) p 

В настоящее время это преобразование реализуется с помощью группы case операторов после поворота данных. Но я чувствую, что, возможно, должно быть что-то, что можно сделать до поворота (чтобы сделать его более элегантным и/или эффективным).

В идеале я хотел бы видеть здесь как можно больше различных подходов к решению этой задачи (любые изменения до или после поворота, неважно).

Количество уровней известно и постоянное (и в этом случае равно 5).

SQL Fiddle образец

ответ

0

SQL-Fiddle очень полезно. Я получил то, что вы хотели, изменив функцию. Вот пересмотренная функция:

create function ftInfo_new(@id int) 
returns table as 
return 
    with Path(ID, ParentID, Name, Level) as 
      (select ID, ParentID, Name, 0 
      from data 
      where ID = @id 
      union all 
      select d.ID, d.ParentID, d.Name, p.Level-1 
      from data d join 
       Path p 
       on p.ParentID = d.ID 
     ) 
    select [1], [2], [3], [4], [5] 
    from (select 1 - Level as Level, Name 
      from Path 
     ) s 
     pivot (max(Name) for Level in ([1], [2], [3], [4], [5])); 

Вы также можете сделать это увеличивая уровни вместо уменьшения их:

create function ftInfo_new(@id int) 
returns table as 
return 
    with Path(ID, ParentID, Name, Level) 
    as 
    (
     select ID, ParentID, Name, 1 
     from data 
     where ID = @id 
     union all 
     select d.ID, d.ParentID, d.Name, p.Level+1 
     from data d join 
      Path p 
      on p.ParentID = d.ID 
    ) 
    select [1], [2], [3], [4], [5] 
    from (select Level as Level, Name 
      from Path 
     ) s 
     pivot (max(Name) for Level in ([1], [2], [3], [4], [5])) p 
+0

Гордон, в исходных данных возьмем строку с 'ID = 4 ', тогда давайте преобразуем строку с тем же идентификатором. Обратите внимание, что данные в столбцах '[1]' to '[5]' должны идти как «Level 1», «Level 2», «Level 3», «Level4», NULL. В ваших вариантах он не только сдвигается, но и получает зеркальное отражение («Уровень 4», «Уровень 3», «Уровень 2», «Уровень1», NULL). –

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