我有一个字符串(表示文件夹路径)。 已知最大级别数(子文件夹) 已知最小级别数(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----|
我该怎么做?
我在想我应该对SUBSTRING
和CHARINDEX
做点什么,但我尝试了一千件事;从来没有做对。当该字符串包含空格时,似乎SUBSTRING
停止在字符串中搜索。
答案 0 :(得分:3)
使用CHARINDEX
和SUBSTRING
是一种很好的方法。请记住,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调用它。
假设文件名是唯一的。