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 フィドルのサンプル

4

1 に答える 1

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
于 2013-08-10T20:42:28.170 に答える