2011-01-12 32 views
3
私は(social.msdn.comで見つかった)Split関数を使用してい

に挿入し、SQLスプリット - 階層的なテーブル構造

SELECT * FROM dbo.Split('/ABC/DEF/GHI/JKL', '/') 

は私が手クエリウィンドウで手動で実行する場合は、次の

Id Name 
-- ---- 
1 
2 ABC 
3 DEF 
4 GHI 
5 JKL 

Idは、元の文字列内の位置を示す連続番号になります。名前は、そのノードの名前です。階層的な情報はまだありません。

次に、これをDBの階層データ構造に入れます。私はストアドプロシージャでこれをやろうとしていますが、私のSQLスキルはそのままで、私は壁を打ちました。ここで私が持っているようをいただきたいものです。(上記のId列をIDまたはここParentIdは列に関連していないことを注意。)

Id ParentId Name FullName 
-- -------- ---- -------- 
1  NULL  ABC /ABC 
2  1  DEF /ABC/DEF 
3  2  GHI /ABC/DEF/GHI 
4  3  JKL /ABC/DEF/GHI/JKL 

私はSPでこれまでのところ持っています( param @FullNameでGetIdと呼ばれる) - GetIdはこのノードに関連付けられたIdを返さなければなりません。ノードが存在しない場合は作成する必要があり、その新しい行のIDを返す必要があります。つまり、このSPのコンシューマはノードが呼び出される前にノードが存在するかどうかを気にしてはいけません。

DECLARE @count int 

-- // is there already a row for this node? 
SELECT @count = COUNT(CatId) 
FROM Category 
WHERE FullName = @FullName 

-- // if no row for this node, create the row 
-- // and perhaps create multiple rows in hierarchy up to root 
IF (@count = 0) 
BEGIN 
    SELECT * FROM Split(@FullName, '/') 
    -- // NOW WHAT ??? 
    -- // need to insert row (and perhaps parents up to root) 
END 

-- // at this point, there should be a row for this node 
-- // return the Id associated with this node 
SELECT Id 
FROM Category 
WHERE FullName = @FullName 

これらのアイテムが最終的に一連の挿入によって終了するカテゴリテーブル(隣接リスト)は、次の構造を持ちます。その結果、

CREATE TABLE Category (
    Id int IDENTITY(1,1) NOT NULL PRIMARY KEY, 
    ParentId int NULL, 
    Name nvarchar(255) NOT NULL, 
    FullName nvarchar(255) NOT NULL) 

、私は、カテゴリテーブルのidカラムの値を生成し、各ノードに適切なParentIdはを取得する必要がありますする必要はありません。

パス '/ ABC/DEF/GHI/JKL'と '/ ABC/DEF/XYZ/LMN/OPQ'を処理してSELECT * FROMカテゴリを実行した後、次のように表示されます。

Id ParentId Name FullName 
-- -------- ---- -------- 
1  NULL  ABC /ABC 
2  1  DEF /ABC/DEF 
3  2  GHI /ABC/DEF/GHI 
4  3  JKL /ABC/DEF/GHI 
5  2  XYZ /ABC/DEF/XYZ 
6  5  LMN /ABC/DEF/XYZ/LMN 
7  6  OPQ /ABC/DEF/XYZ/LMN/OPQ 

Q:ノードが存在していたか、我々は最終的な親会社であっなるまで再帰的に、最も外側のノードから始まるSPにコールバックすることは可能でしょうか?効果に何か:

GetId(@FullName) 
{ 
If Category exists with @FullName 
    return CatId 
Else // row doesn't exist for this node 
    Split @FullName, order by Id DESC so we get the leaf node first 
    Create Category row 
     @FullName, 
     @Name, 
     @ParentId = Id of next FullName (call GetId with FullName of next row from Split) 
} 
+0

どのバージョンのSQL Serverを使用していますか? 2008の場合は[hierarchyid](http://msdn.microsoft.com/en-us/magazine/cc794278.aspx)と考えていますか? –

+0

私はSQL Server 2008を使っています –

+0

パスを示す方法は、 'hierarchyid'形式をかなり思い出しました。私は実際には自分自身を使用していませんが、隣接リストモデルよりもあなたの目的に適しているかどうかはわかりません。 –

答えて

3

あなたは第二の部分のための今すぐ

With TMP AS (
    SELECT Id, Data as Name, RN=ROW_NUMBER() over (Order by Id ASC) 
    FROM dbo.Split('/ABC/DEF/GHI/JKL', '/') 
    where Data > '' 
), TMP2 AS (
    SELECT TOP 1 RN, CONVERT(bigint, null) ParentId, Name, convert(nvarchar(max),'/' + Name) FullName 
    From TMP 
    Order by RN 
    union all 
    SELECT n.RN, t.RN, n.Name, t.FullName + '/' + n.Name 
    from TMP2 t 
    inner join TMP n on n.RN = t.RN+1) 
select * 
from tmp2 
order by RN 

RowNumbering

との組み合わせで、これを実現するためにCTEを使用することができますが、これは階層全体を挿入しますが、ID = 1で始まります

IF (@count = 0) 
BEGIN 
    With TMP AS (
     SELECT Id, Data as Name, RN=ROW_NUMBER() over (Order by Id ASC) 
     FROM dbo.Split('/ABC/DEF/GHI/JKL', '/') 
     where Data > '' 
    ), TMP2 AS (
     SELECT TOP 1 RN, CONVERT(bigint, null) ParentId, Name, convert(nvarchar(max),'/' + Name) FullName 
     From TMP 
     Order by RN 
     union all 
     SELECT n.RN, t.RN, n.Name, t.FullName + '/' + n.Name 
     from TMP2 t 
     inner join TMP n on n.RN = t.RN+1) 
    insert Category(CatId, ParentId, Name, FullName) --<< list correct column names 
    select RN, ParentId, Name, FullName 
    from tmp2 
    order by RN 
END 
+0

私はあなたが第2部で何をしたいかまだ分かりません。最後の(再)構築されたFullNameは入力@FullNameと一致することは間違いないので、分割の目的は何ですか? – RichardTheKiwi

+0

@cyberwiki私は隣接リストDBスキーマに階層構造を生成する一連の挿入を行いたいと思います。私は、上記のソリューションがインサートシナリオにどのように適合するかはわかりません。 –

+0

@ Ed.S。まだ100%確実ではない。 _full_名が存在するかどうかをテストし、ツリー全体が挿入されていない場合(たとえば、/ ABCがすでに他の場所に存在する可能性があるなど) IDはID列に入り、parentIDを調整する必要がありますか? – RichardTheKiwi

関連する問題