将字符串拆分为表格

时间:2012-11-16 14:34:37

标签: sql sql-server string sql-server-2008 tsql

我有一个字符串(表示文件夹路径)。 已知最大级别数(子文件夹) 已知最小级别数(root不包含文件)。 foldernames可以包含空格。 没有迹象表明示例中的文件夹是文件夹还是文件............. 我希望将该字符串拆分为列。

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停止在字符串中搜索。

2 个答案:

答案 0 :(得分:3)

使用CHARINDEXSUBSTRING是一种很好的方法。请记住,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, '/', '')轻松完成。

答案 1 :(得分:1)

我可以指出你的方向(没时间写一个解决方案)。

由于嵌套级别已知,您可以计算反斜杠的数量(也称为嵌套级别),并使用CASE来处理每个方案。然后在每个CASE块中,获取最深级别的文件夹并更新表。您可以拥有一个UDF,以便可以为每个INSERT调用它。

假设文件名是唯一的。