2016-08-18 8 views
2

私は、サーバー上のファイルを参照するMSSQLServerデータベースに読み取り専用でアクセスしています。SQLツリーファイル構造 - ファイルパスを取得

2つのテーブルは、ファイル構造を表すために使用される:

folderInfo 
------------------------------------------------- 
| id | parentId | Sequence | folderName | 
|------------------------------------------------ 
| 1 |  0  |  1  |  folder1 | 
| 2 |  0  |  2  |  folder2 | 
| 3 |  1  |  1  | subfolder1 | 
------------------------------------------------- 

fileInfo 
----------------------------------------------- 
| id | folderId | Sequence | fileName | 
|---------------------------------------------- 
| 1 |  3  |  1 | e.xml | 
| 2 |  2  |  1 | a.xml | 
| 3 |  2  |  2 | f.xml | 
----------------------------------------------- 

「PARENTID = 0」フォルダは、ファイル構造のルートであることを意味します。

私は私に(ルートからの相対)ファイルパスを与えることができる組合と、すべてのファイルに対するクエリを作成する方法を見当もつかない。

は、ファイルの数のオーダーが10000であることを考えると、私は、各ファイルのために再度照会する必要がありますする必要はありません(または私は間違っている、これは非効率的だと思うことになっています?)。

私はその記事では答えの始まりを発見した: SQL Tree Structure

with recursive full_tree as (
    select id, name, parent, 1 as level 
    from departments 
    where parent is null 
    union all 
    select c.id, c.name, c.parent, p.level + 1 
    from departments c 
    join full_tree p on c.parent = p.id 
) 
select * 
from full_tree; 

しかし、私は私のようなものになるだろうこれは、私が必要なものにこれを回すことができるかわからない:

fileInfo 
---------------------------------------------------- 
| id | Sequence | filepath      | 
|--------------------------------------------------- 
| 1 |  1 | /folder1/subfolder1/e.xml | 
| 2 |  1 | /folder2/a.xml    | 
| 3 |  2 | /folder2/f.xml    | 
---------------------------------------------------- 

答えて

1

この

Declare @FolderInfo table (id int,parentId int,Sequence int, folderName varchar(100)) 
Insert into @FolderInfo values (1,0,1,'folder1'),(2,0,2,'folder2'),(3,1,1,'subfolder1') 

Declare @FileInfo table (id int,folderId int,Sequence int, fileName varchar(100)) 
Insert into @FileInfo values (1 ,3 ,1,'e.xml'),(2 ,2 ,1,'a.xml'),(3 ,2 ,2,'f.xml') 

のようなものの
;with cteHB (Seq,ID,parentId,Lvl,folderPath) as (
    Select Seq = cast(1000+Row_Number() over (Order by folderName) as varchar(500)) 
      ,ID 
      ,parentId 
      ,Lvl=1 
      ,folderPath = cast('/'+folderName as varchar(500)) 
    From @FolderInfo 
    Where parentId = 0 
    Union All 
    Select Seq = cast(concat(cteHB.Seq,'.',1000+Row_Number() over (Order by cteCD.Sequence)) as varchar(500)) 
      ,cteCD.ID 
      ,cteCD.parentId,cteHB.Lvl+1 
      ,folderPath = cast(concat(cteHB.folderPath,'/',cteCD.folderName) as varchar(500)) 
    From @FolderInfo cteCD 
    Join cteHB on cteCD.parentId = cteHB.ID) 
Select B.ID 
     ,B.Sequence 
     ,folderPath=A.folderPath+'/'+B.fileName 
From cteHB A 
Join @FileInfo B on (B.folderId =A.ID) 
Order By A.Seq    

戻り

ID Sequence folderPath 
1 1   /folder1/subfolder1/e.xml 
2 1   /folder2/a.xml 
3 2   /folder2/f.xml 
+0

は、SQLウィザードをありがとう! データベースが_SQLServer2008R2_であるため、concatはサポートされていないため、代わりに '+'を使用しました。私は連結エラー(タイプミスマッチのもの)に遭遇したので、混乱を引き起こしていたすべてのintを変換するために 'cast(...としてvarchar(500)) 'を使用しました。 – T4GG

+0

ちょうど好奇心から、なぜ 'cteHB'と' cteCD'ですか? – T4GG

+0

@ T4GG遅く応答して申し訳ありません。 cteHB(私の小さな頭の中)はcte Hierarchy Buildで、CDはCore Dataです。私には意味がある名前だけ –

関連する問題