2017-05-16 2 views
1

フォルダパスを含むテーブルがあります。 この表には、DirID,BaseDirID,DirLevelおよびDisplayPathの4つの列が含まれています。 DirID - フォルダのIDです。 BaseDirID - 階層内の最初のフォルダのIDです。したがって、同じ階層のすべてのフォルダ(パス)はこの列の同じ値を共有します。 DirLevel - フォルダの深さ。 DisplayPath - フォルダのパス。SQL:分割された階層のフォルダパスが見つからない

階層内のこれらのフォルダ間の「ギャップ」をすべて見つける必要があります。例えば

サンプルデータ:

BaseDirID DisplayPath 
1 'A\B' 
1 'A\B\C\D' 
1 'A\B\F\G' 
2 'U\V' 
2 'U\V\W\X' 
2 'U\V\M\L' 

コメント:

DirID BaseDirID DirLevel DisplayPath 
1 1 1 'A' 
2 1 3 'A\B\C' 
3 1 5 'A\B\C\D\E' 
4 1 3 'A\B\F' 
5 1 5 'A\B\F\G\H' 
6 2 1 'U' 
7 2 3 'U\V\W' 
8 2 5 'U\V\W\X\Y' 
9 2 3 'U\V\M' 
10 2 5 'U\V\M\L\O' 

だから、私たちは次のようなデータを見つける必要があります。このテーブルには、フォルダのレコードが255,000以上あり、なので、最も効率的な方法であるを探しています。それ以外の場合、スクリプトは長く保存されません。

b。私はすべてのフォルダのリストを持っていません。私が持っているのは、 "ルート"フォルダと "リーフ"フォルダで、階層内の "ギャップ"を見つける必要があります。

c。テーブルには複数の階層があり、すべての階層で「ギャップ」を見つける必要があります。

d。サンプルデータで見られるように、各階層は分割できます。最初の階層は、 'A \ B'フォルダの2つのフォルダパス( 'A \ B \ C'と 'A \ B \ F')に分割されます。 2番目の階層は、 'U \ V'フォルダから 'U \ V \ W'と 'U \ V \ M'の2つのフォルダパスに分割されます。 階層が分割されている場合でも、すべての「ギャップ」を見つける必要があります。

e。 SQL Serverのバージョンは次のとおりです。SQL 2012 SP3。

この質問は、次のリンクで質問された質問の続きです。SQL: Find missing hierarchy Folders (Paths) in a table 太字で表示される第4コメントもあります。

"hierarchyid"(sql server 2008から始まる)という新しい列型があることがわかりました。私はそれが私たちを助けるかもしれないと思った - https://docs.microsoft.com/en-us/sql/t-sql/data-types/hierarchyid-data-type-method-reference どう思いますか?

ありがとうございます。パス内の複数の不足しているフォルダを表示するには、この追加パス(11,2,'U\V\Z\L\O\Q\R\S\T')を使用して

+0

実フォルダ名が異なっているか、それは次のようになりますA \ B ...? Kannan Kannan \ Kandasamy Kannan \ Kandasamy \ Nuriel Kannan \ Kandasamy \ Nuriel \ Zrubavely –

+0

フォルダ名は次のように何もすることができます。 –

答えて

1

with cte as (
select BaseDirID, DisplayPath = left(DisplayPath,len(DisplayPath)-charindex('\',reverse(DisplayPath))) 
from t 
where DirLevel > 1 
    and not exists (
    select 1 
    from t i 
    where t.BaseDirId = i.BaseDirId 
    and i.DisplayPath = left(t.DisplayPath,len(t.DisplayPath)-charindex('\',reverse(t.DisplayPath))) 
    ) 
union all 
select BaseDirID, DisplayPath = left(DisplayPath,len(DisplayPath)-charindex('\',reverse(DisplayPath))) 
from cte t 
where not exists (
    select 1 
    from t i 
    where t.BaseDirId = i.BaseDirId 
    and i.DisplayPath = left(t.DisplayPath,len(t.DisplayPath)-charindex('\',reverse(t.DisplayPath)))             
    ) 
) 
select distinct * 
from cte 

rextesterデモ:http://rextester.com/CEVGZ96613

リターン:

+-----------+-----------------+ 
| BaseDirID | DisplayPath | 
+-----------+-----------------+ 
|   1 | A\B    | 
|   1 | A\B\C\D   | 
|   1 | A\B\F\G   | 
|   2 | U\V    | 
|   2 | U\V\M\L   | 
|   2 | U\V\W\X   | 
|   2 | U\V\Z   | 
|   2 | U\V\Z\L   | 
|   2 | U\V\Z\L\O  | 
|   2 | U\V\Z\L\O\Q  | 
|   2 | U\V\Z\L\O\Q\R | 
|   2 | U\V\Z\L\O\Q\R\S | 
+-----------+-----------------+ 
+0

私は再帰的な不足しているフォルダが必要です: –

+0

このソリューションは効率的ですか? CharIndex()を25万行を含むテーブルの各行で複数回使用するため... –

+0

私はこのソリューションを〜200kのサイズのテーブルで試しました。 キャンセルするまで、クエリは20分以上実行されました。 より効率的なソリューションを教えてください。 「この表には250,000件以上のフォルダのレコードが含まれているので、最も効率的な方法を探しています」という疑問で非常に明確に書いています。 –

関連する問題