2

文字列 (フォルダー パスを表す) があります。レベルの最大数はわかっています (サブサブフォルダー) レベルの最小数はわかっています (ルートにはファイルが含まれていません)。フォルダ名にはスペースを含めることができます。例の a がフォルダーなのかファイルなのかが示されていません..............その文字列を列に分割したい。

CREATE TABLE TESTDATA([path] [nvarchar](max))
INSERT INTO TESTDATA (path) VALUES (N'/a/)
INSERT INTO TESTDATA (path) VALUES (N'/a/ab/filename1)
INSERT INTO TESTDATA (path) VALUES (N'/a/ab/abc/filename2)
INSERT INTO TESTDATA (path) VALUES (N'/a/ab/abc/filename3)
INSERT INTO TESTDATA (path) VALUES (N'/a/ab/abc/abcd/filename4)
INSERT INTO TESTDATA (path) VALUES (N'/a/ac/ac e/filename5)

TESTDATA は次のようになります

|----------path-----------------|
/a
/a/ab/filename1
/a/ab/abc/filename2
/a/ab/abc/filename3
/a/ab/abc/abcd/filename4
/a/ac/ac e/filename5

しかし、私はそれが次のように見える必要があります

filename--|--root--|--folder--|--subfolder--|--subsubfolder--|
----------|--------|----------|-------------|----------------|
filename1-|---a----|----ab----|
filename2-|---a----|----ab----|-----abc-----|
filename3-|---a----|----ab----|-----abc-----|
filename4-|---a----|----ab----|-----abc-----|-------abcd-----|
filename5-|---a----|----ac----|-----ac e----|

これについてどうすればいいですか?

私は何かをすべきだと思っていますSUBSTRINGCHARINDEX、私は何千ものことを試しました。それを正しくすることはありません。SUBSTRING文字列にスペースが含まれていると、文字列の検索が停止するようです。

4

2 に答える 2

3

CHARINDEXandを使用SUBSTRINGするのは良いアプローチです。CHARINDEX検索の開始点を指定する 3 番目のパラメーターを使用できることを思い出してください。/これを使用して、2 番目、3 番目などを見つけることができます/。この問題を解決する 1 つの方法は、相互に構築されたサブクエリを使用して、一度に問題の小さな部分を 1 つずつ攻撃することです。以下は、連続する Common-Table Expressions を使用して、ファイル名をサブサブ フォルダー レベルに分解する例です。

with root as (
  select
    path,
    left(path, charindex('/', path, 2) - 1) as root,
    substring(path, charindex('/', path, 2), 1000) as rest
  from testdata
), folder as (
  select
    path,
    root,
    case when charindex('/', rest, 2) > 0
      then left(rest, charindex('/', rest, 2) - 1)
      else '' 
    end as folder,
    case when charindex('/', rest, 2) > 0
      then substring(rest, charindex('/', rest, 2), 1000)
      else rest
    end as rest
  from root
), subfolder as (
  select
    path,
    root,
    folder,
    case when charindex('/', rest, 2) > 0
      then left(rest, charindex('/', rest, 2) - 1)
      else '' 
    end as subfolder,
    case when charindex('/', rest, 2) > 0
      then substring(rest, charindex('/', rest, 2), 1000)
      else rest
    end as rest
  from folder
), subsubfolder as (
  select
    path,
    root,
    folder,
    subfolder,
    case when charindex('/', rest, 2) > 0
      then left(rest, charindex('/', rest, 2) - 1)
      else '' 
    end as subsubfolder,
    case when charindex('/', rest, 2) > 0
      then substring(rest, charindex('/', rest, 2), 1000)
      else rest
    end as rest
  from subfolder
)
select
  path,
  rest as filename,
  root,
  folder,
  subfolder,
  subsubfolder
from subsubfolder;

デモ: http://www.sqlfiddle.com/#!3/e91eb/36

サンプル出力:

PATH                      FILENAME    ROOT  FOLDER  SUBFOLDER  SUBSUBFOLDER
------------------------  ----------  ----  ------  ---------  ------------  
/a/                       /           /a               
/a/ab/filename1           /filename1  /a    /ab          
/a/ab/abc/filename2       /filename2  /a    /ab     /abc     
/a/ab/abc/filename3       /filename3  /a    /ab     /abc     
/a/ab/abc/abcd/filename4  /filename4  /a    /ab     /abc       /abcd
/a/ac/ac e/filename5      /filename5  /a    /ac     /ac e

注:/フォルダー名の一部として保持していた を削除するには、SUBSTRING(part, 2, 1000)またはを使用して簡単に行うことができますSUBSTITUTE(part, '/', '')

于 2012-11-16T14:54:53.377 に答える
1

方向性を示すことができます (解決策を書く時間がありませんでした)。

入れ子のレベルがわかっているため、バックスラッシュの数 (別名、入れ子のレベル) を数えて、各シナリオを処理する CASE を用意できます。次に、各 CASE ブロックで、最も深いレベルのフォルダーを取得し、テーブルを更新します。各 INSERT に対して呼び出すことができるように、UDF を持つことができます。

ファイル名は一意であることが前提です。

于 2012-11-16T14:44:13.790 に答える