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

使用CHARINDEXandSUBSTRING是一个很好的方法。请记住,CHARINDEX可以采用第三个参数来指定搜索的起点。使用它,您可以找到第二个/和第三个/,依此类推。解决问题的一种方法是使用相互构建的子查询并一次解决一小部分问题。这是一个使用连续通用表表达式将文件名分解为子文件夹级别的示例:

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 块中,获取最深级别的文件夹并更新表。您可以拥有一个 UDF,以便您可以为每个 INSERT 调用它。

假设是文件名是唯一的。

于 2012-11-16T14:44:13.790 回答