如何在定界符之间多次提取字符串的一部分并输入到新列 T-SQL
How to extract part of a string numerous times between delimiters and input into new columns T-SQL
我想从一个具有多个相同分隔符的值中多次提取字符串的一部分,并将提取的字符串放入新列中。
这是我正在使用的数据示例(这些文件夹路径可能更长,具体取决于文件夹的深度):
文件夹路径:
Q:\downloads\extraction\bee\honey\
Q:\desktop\chocolate\london\time\spring\
Q:\documents\cars\astonmartin\vanquish\
我想从左边的分隔符之间提取整个字符串,并将它们放入字符串不同阶段的新列中,例如
FolderPath
RootDirectory
SubDirectory
SubSubDirectory
Q:\documents\cars\astonmartin\vanquish\
Q:\documents
Q:\documents\cars
Q:\documents\cars\astonmartin
我只是想知道这是否可行,尤其是当文件夹名称具有不同长度的所有类型时。
如有任何帮助,我将不胜感激 - 谢谢!
已更新(使用第二个解决方案)
解决方案 #1 - Charindex + 级联应用:
--==== Sample Data
DECLARE @folders TABLE (Folder VARCHAR(1000));
INSERT @folders VALUES
('Q:\downloads\extraction\bee\honey\'),
('Q:\desktop\chocolate\london\time\spring\'),
('Q:\documents\cars\astonmartin\vanquish\');
SELECT FolderParse.*
FROM @folders AS f
CROSS APPLY
(
SELECT
FolderPath = f.Folder,
RootDirectory = SUBSTRING(f.Folder, 1, p2.Pos-2),
SubDirectory = SUBSTRING(f.Folder, 1, p3.Pos-1),
SubSubDirectory = SUBSTRING(f.Folder, 1, p4.Pos-1)
FROM (VALUES(CHARINDEX('\',f.Folder))) AS p1(Pos)
CROSS APPLY (VALUES(CHARINDEX('\',f.Folder,p1.Pos+1))) AS p2(Pos)
CROSS APPLY (VALUES(CHARINDEX('\',f.Folder,p2.Pos+1))) AS p3(Pos)
CROSS APPLY (VALUES(CHARINDEX('\',f.Folder,p3.Pos+1))) AS p4(Pos)
) AS folderParse;
结果:
FolderPath RootDirectory SubDirectory SubSubDirectory
----------------------------------------- -------------- ----------------------- ---------------------------------
Q:\downloads\extraction\bee\honey\ Q:\downloads Q:\downloads\extraction Q:\downloads\extraction\bee
Q:\desktop\chocolate\london\time\spring\ Q:\desktop Q:\desktop\chocolate Q:\desktop\chocolate\london
Q:\documents\cars\astonmartin\vanquish\ Q:\documents Q:\documents\cars Q:\documents\cars\astonmartin
解决方案 #2 - Tally Table:
第一个解决方案是可行的方法,但当您需要更深入时,第二个解决方案更好。为此,您需要获取 fnTally.
的副本
以下是针对一个字符串执行此操作的方法:
DECLARE @string VARCHAR(1000) = 'Q:\documents\cars\astonmartin\vanquish\';
SELECT
FolderPath = @string,
RootDirectory = MAX(CASE f.RN WHEN 1 THEN f.FPath END),
SubDirectory = MAX(CASE f.RN WHEN 2 THEN f.FPath END),
SubSubDirectory = MAX(CASE f.RN WHEN 3 THEN f.FPath END)
FROM
(
SELECT ROW_NUMBER() OVER (ORDER BY t.N), SUBSTRING(@string,1,t.N+2)
FROM (VALUES(SUBSTRING(@string,4,1000))) AS s(Txt)
CROSS APPLY dbo.fnTally(1,LEN(s.Txt)) AS t
WHERE SUBSTRING(s.Txt,t.N,1) = '\'
) AS f(RN,FPath);
Returns:
FolderPath RootDirectory SubDirectory SubSubDirectory
---------------------------------------- ------------------ --------------------- --------------------------------
Q:\documents\cars\astonmartin\vanquish\ Q:\documents Q:\documents\cars Q:\documents\cars\astonmartin
反对 table:
--==== Sample Data
DECLARE @folders TABLE (Folder VARCHAR(1000));
INSERT @folders VALUES
('Q:\downloads\extraction\bee\honey\'),
('Q:\desktop\chocolate\london\time\spring\'),
('Q:\documents\cars\astonmartin\vanquish\');
--==== Solution
SELECT DirectoryParse.*
FROM @folders AS fld
CROSS APPLY
(
SELECT
FolderPath = fld.Folder,
RootDirectory = MAX(CASE f.RN WHEN 1 THEN f.FPath END),
SubDirectory = MAX(CASE f.RN WHEN 2 THEN f.FPath END),
SubSubDirectory = MAX(CASE f.RN WHEN 3 THEN f.FPath END)
FROM
(
SELECT ROW_NUMBER() OVER (ORDER BY t.N), SUBSTRING(fld.Folder,1,t.N+2)
FROM (VALUES(SUBSTRING(fld.Folder,4,1000))) AS s(Txt)
CROSS APPLY dbo.fnTally(1,LEN(s.Txt)) AS t
WHERE SUBSTRING(s.Txt,t.N,1) = '\'
) AS f(RN,FPath)
) AS DirectoryParse;
结果:
FolderPath RootDirectory SubDirectory SubSubDirectory
----------------------------------------- -------------- ----------------------- ---------------------------------
Q:\downloads\extraction\bee\honey\ Q:\downloads Q:\downloads\extraction Q:\downloads\extraction\bee
Q:\desktop\chocolate\london\time\spring\ Q:\desktop Q:\desktop\chocolate Q:\desktop\chocolate\london
Q:\documents\cars\astonmartin\vanquish\ Q:\documents Q:\documents\cars Q:\documents\cars\astonmartin
我想从一个具有多个相同分隔符的值中多次提取字符串的一部分,并将提取的字符串放入新列中。
这是我正在使用的数据示例(这些文件夹路径可能更长,具体取决于文件夹的深度):
文件夹路径:
Q:\downloads\extraction\bee\honey\
Q:\desktop\chocolate\london\time\spring\
Q:\documents\cars\astonmartin\vanquish\
我想从左边的分隔符之间提取整个字符串,并将它们放入字符串不同阶段的新列中,例如
FolderPath | RootDirectory | SubDirectory | SubSubDirectory |
---|---|---|---|
Q:\documents\cars\astonmartin\vanquish\ | Q:\documents | Q:\documents\cars | Q:\documents\cars\astonmartin |
我只是想知道这是否可行,尤其是当文件夹名称具有不同长度的所有类型时。
如有任何帮助,我将不胜感激 - 谢谢!
已更新(使用第二个解决方案)
解决方案 #1 - Charindex + 级联应用:
--==== Sample Data
DECLARE @folders TABLE (Folder VARCHAR(1000));
INSERT @folders VALUES
('Q:\downloads\extraction\bee\honey\'),
('Q:\desktop\chocolate\london\time\spring\'),
('Q:\documents\cars\astonmartin\vanquish\');
SELECT FolderParse.*
FROM @folders AS f
CROSS APPLY
(
SELECT
FolderPath = f.Folder,
RootDirectory = SUBSTRING(f.Folder, 1, p2.Pos-2),
SubDirectory = SUBSTRING(f.Folder, 1, p3.Pos-1),
SubSubDirectory = SUBSTRING(f.Folder, 1, p4.Pos-1)
FROM (VALUES(CHARINDEX('\',f.Folder))) AS p1(Pos)
CROSS APPLY (VALUES(CHARINDEX('\',f.Folder,p1.Pos+1))) AS p2(Pos)
CROSS APPLY (VALUES(CHARINDEX('\',f.Folder,p2.Pos+1))) AS p3(Pos)
CROSS APPLY (VALUES(CHARINDEX('\',f.Folder,p3.Pos+1))) AS p4(Pos)
) AS folderParse;
结果:
FolderPath RootDirectory SubDirectory SubSubDirectory
----------------------------------------- -------------- ----------------------- ---------------------------------
Q:\downloads\extraction\bee\honey\ Q:\downloads Q:\downloads\extraction Q:\downloads\extraction\bee
Q:\desktop\chocolate\london\time\spring\ Q:\desktop Q:\desktop\chocolate Q:\desktop\chocolate\london
Q:\documents\cars\astonmartin\vanquish\ Q:\documents Q:\documents\cars Q:\documents\cars\astonmartin
解决方案 #2 - Tally Table:
第一个解决方案是可行的方法,但当您需要更深入时,第二个解决方案更好。为此,您需要获取 fnTally.
的副本以下是针对一个字符串执行此操作的方法:
DECLARE @string VARCHAR(1000) = 'Q:\documents\cars\astonmartin\vanquish\';
SELECT
FolderPath = @string,
RootDirectory = MAX(CASE f.RN WHEN 1 THEN f.FPath END),
SubDirectory = MAX(CASE f.RN WHEN 2 THEN f.FPath END),
SubSubDirectory = MAX(CASE f.RN WHEN 3 THEN f.FPath END)
FROM
(
SELECT ROW_NUMBER() OVER (ORDER BY t.N), SUBSTRING(@string,1,t.N+2)
FROM (VALUES(SUBSTRING(@string,4,1000))) AS s(Txt)
CROSS APPLY dbo.fnTally(1,LEN(s.Txt)) AS t
WHERE SUBSTRING(s.Txt,t.N,1) = '\'
) AS f(RN,FPath);
Returns:
FolderPath RootDirectory SubDirectory SubSubDirectory
---------------------------------------- ------------------ --------------------- --------------------------------
Q:\documents\cars\astonmartin\vanquish\ Q:\documents Q:\documents\cars Q:\documents\cars\astonmartin
反对 table:
--==== Sample Data
DECLARE @folders TABLE (Folder VARCHAR(1000));
INSERT @folders VALUES
('Q:\downloads\extraction\bee\honey\'),
('Q:\desktop\chocolate\london\time\spring\'),
('Q:\documents\cars\astonmartin\vanquish\');
--==== Solution
SELECT DirectoryParse.*
FROM @folders AS fld
CROSS APPLY
(
SELECT
FolderPath = fld.Folder,
RootDirectory = MAX(CASE f.RN WHEN 1 THEN f.FPath END),
SubDirectory = MAX(CASE f.RN WHEN 2 THEN f.FPath END),
SubSubDirectory = MAX(CASE f.RN WHEN 3 THEN f.FPath END)
FROM
(
SELECT ROW_NUMBER() OVER (ORDER BY t.N), SUBSTRING(fld.Folder,1,t.N+2)
FROM (VALUES(SUBSTRING(fld.Folder,4,1000))) AS s(Txt)
CROSS APPLY dbo.fnTally(1,LEN(s.Txt)) AS t
WHERE SUBSTRING(s.Txt,t.N,1) = '\'
) AS f(RN,FPath)
) AS DirectoryParse;
结果:
FolderPath RootDirectory SubDirectory SubSubDirectory
----------------------------------------- -------------- ----------------------- ---------------------------------
Q:\downloads\extraction\bee\honey\ Q:\downloads Q:\downloads\extraction Q:\downloads\extraction\bee
Q:\desktop\chocolate\london\time\spring\ Q:\desktop Q:\desktop\chocolate Q:\desktop\chocolate\london
Q:\documents\cars\astonmartin\vanquish\ Q:\documents Q:\documents\cars Q:\documents\cars\astonmartin