【问题标题】:Split string in column and add value in column在列中拆分字符串并在列中添加值
【发布时间】:2014-08-13 10:29:00
【问题描述】:

我有一个包含几行数据的表格,如下所示:

16  W:\2-Work\ALBO\00_Proposal\ALxO_Amendement #1_20091022_signed.pdf
17  W:\2-Work\ALBO\00_Proposal\Level1\ALBO_Amendment #1_20110418.docx
18  W:\2-Work\ALBO\00_Proposal\A\BR\T\X_#1_20110418_final.docx
19  W:\2-Work\ALBO\MyOptionl\AO_Amendment_2 August 2013.docx

我创建了从Col1Col10 的列

我想用分隔符'\'分隔每个值

这个想法是在每一列上都有:

Col1 | Col2 | Col3 | Col4 | Col5 |etc...

W:  2-Work  ALBO  00_Proposal ALxO_Amendement #1_20091022_signed.pdf

我知道如何使用charindexsubstring,但每行(8500 行)的“\”数不同。

你能帮帮我吗?

我使用的是 Microsoft SQL Server 2012。

非常感谢

编辑 2014/06/24

我的目标是生成完整路径和拆分路径的 XML。

其实这是我的想法:

1 - 识别临时表中的所有 ID 进行循环

--On déclare une table tempo 声明@IdTable 表( id int, src nvarchar(max))

--Injecte tous les id exists de la table 插入@IdTable (id, src) 从albo中选择id、src

--on déclare l'id de début en commencant par le plus petit 声明 @id int = (select min(id) from ALBO)

--Tnat qu'il reste des ID on continue la boucle 而@id 不为空 开始

打印@id 从@IdTable 中选择@id = min(id),其中ID > @id 结尾 --Fin de la boucle des ID

2 - 拆分每一行并更新列(Colx => 之前已经创建了 Clolumns) 这段代码应该放在我之前的循环中。

声明@products varchar(max) = 'W:\2-Work\ALBO\13_WP Reporting\13_07_Monthly reports\13_07_01 Archives\2012\201211\Draft\ALBO-MR-201211\gp_scripts\v1\Top10_duree_final.txt' 声明@individual varchar(max) = null

WHILE LEN(@products) > 0 开始 如果 PATINDEX('%\%',@products) > 0 开始 SET @individual = SUBSTRING(@products, 0, PATINDEX('%\%',@products)) 选择@individual --我必须用ID制作和更新

    SET @products = SUBSTRING(@products, LEN(@individual + '\') + 1,
                                                 LEN(@products))
END
ELSE
BEGIN
    SET @individual = @products
    SET @products = NULL
    print @individual
END

结束

【问题讨论】:

  • 这不是一个好的表格设计。你想做什么?
  • 您可以创建一个函数,通过“\”拆分数据并为每一行返回一个表,然后使用拆分函数中的插入语句将表插入 col1 到 col10。尝试编写代码来实现上述内容,以防您遇到我们在这里的问题! :)
  • 你不是把'\'换成''吗?
  • 我想“分解”该行并将“Col1”更新为“Col10”,其值如下:“This\Is\My\Sentence”=> Col1:This | Col2 : 是 | Col3 : 我的 | Col4 : 句子
  • 您要解决的真正问题是什么?为什么您认为创建 10 个任意列是解决此问题的方法? (不是)。如果您正在尝试收集有关文件夹的统计信息,还有其他方法可以做到这一点

标签: sql tsql sql-server-2012


【解决方案1】:

正如其他人所说,这可能不是最好的做事方式,如果你解释你将如何处理结果,它可能会帮助我们提供更好的选择

[另外,由于某种原因,下面代码的颜色显示得很奇怪,因此请将其复制并粘贴到您的 Sql 服务器中以便更好地查看]

drop table #Path

create table #Path (item bigint,location varchar(1000))

insert into #Path 
select 16  ,'W:\2-Work\ALBO\00_Proposal\ALxO_Amendement #1_20091022_signed.pdf' union
select 17  ,'W:\2-Work\ALBO\00_Proposal\Level1\ALBO_Amendment #1_20110418.docx' union
select 18  ,'W:\2-Work\ALBO\00_Proposal\A\BR\T\X_#1_20110418_final.docx' union
select 19  ,'W:\2-Work\ALBO\MyOptionl\AO_Amendment_2 August 2013.docx'


select * from #Path;


with Path_Expanded(item,subitem,location, start, ending, split)
as(
select item
     , 1 --subitem begins at 1
     , location -- full location path
     , 0 --start searching the file from the 0 position
     , charindex('\',location) -- find the 1st '\' charactor
     , substring(location,0,charindex('\',location)) --return the string from the start position, 0, to the 1st '\' charactor

from #Path
union all
select item
     , subitem+1 --add 1 to subitem
     , location -- full location path
     , ending+1 -- start searching the file from the position after the last '\' charactor
     , charindex('\',location,ending+1)-- find the 1st '\' charactor that occurs after the last '\' charactor found
     , case when charindex('\',location,ending+1) = 0 then substring(location,ending+1,1000) --if you cant find anymore '\', return everything else after the last '\'
            else substring(location,ending+1, case when charindex('\',location,ending+1)-(ending+1) <= 0 then 0 
            else charindex('\',location,ending+1)-(ending+1) end )--returns the string between the last '\' charactor and the next '\' charactor
            end 

from Path_Expanded
where ending > 0 --stop once you can't find anymore '\' charactors
)


--pivots the results 
select item
    , max(case when subitem = 1 then split else '' end) as col1
    , max(case when subitem = 2 then split else '' end) as col2
    , max(case when subitem = 3 then split else '' end) as col3
    , max(case when subitem = 4 then split else '' end) as col4
    , max(case when subitem = 5 then split else '' end) as col5
    , max(case when subitem = 6 then split else '' end) as col6
    , max(case when subitem = 7 then split else '' end) as col7
    , max(case when subitem = 8 then split else '' end) as col8
    , max(case when subitem = 9 then split else '' end) as col9
    , max(case when subitem = 10 then split else '' end) as col10

from Path_Expanded
group by item

您可能更喜欢将每个文件夹放在自己的行中,如果是这样,请将上面的数据透视部分替换为下面的查询

select  item
      , subitem
      , location
      , split from Path_Expanded where item = 16

【讨论】:

  • 我的目标是创建一个 XML 宽度的所有“公开”信息并保留原始路径。
【解决方案2】:

以下查询将获得您要查找的内容;正如其他人所指出的,这不是一个特别好的设计。例如,当您查找文件名并且每次都在不同的列中时会发生什么?

无论如何,这将满足您的要求(甚至可能是您想要的):

-- Test Data
CREATE TABLE #FilePath (FileNumber INT IDENTITY(1,1), FilePath VARCHAR(1000))
INSERT INTO #FilePath (FilePath) 
SELECT 'W:\2-Work\ALBO\00_Proposal\ALxO_Amendement #1_20091022_signed.pdf' UNION
SELECT 'W:\2-Work\ALBO\00_Proposal\Level1\ALBO_Amendment #1_20110418.docx' UNION
SELECT 'W:\2-Work\ALBO\00_Proposal\A\BR\T\X_#1_20110418_final.docx' UNION
SELECT 'W:\2-Work\ALBO\MyOptionl\AO_Amendment_2 August 2013.docx'
GO

-- Numbers CTE
WITH Numbers AS
(
    SELECT n = 1
    UNION ALL
    SELECT n + 1
    FROM Numbers
    WHERE n+1 <= 1000 -- set this to the maximum length of your file path
)

SELECT 
    FilePath,
    [1] AS Col1,
    [2] AS Col2,
    [3] AS Col3,
    [4] AS Col4,
    [5] AS Col5,
    [6] AS Col6,
    [7] AS Col7,
    [8] AS Col8,
    [9] AS Col9,
    [10] AS Col10
FROM 
  (
    SELECT 
        FilePath, 
        ROW_NUMBER() OVER (PARTITION BY FilePath ORDER BY n) RowNum,
        CAST(LTRIM(RTRIM(NULLIF(SUBSTRING('\' + FilePath + '\' , n , CHARINDEX('\' ,     '\' + FilePath + '\' , n) - n) , ''))) AS VARCHAR(1000)) FolderName
    FROM Numbers, #FilePath
    WHERE 
        n <= Len('\' + FilePath + '\') AND SubString('\' + FilePath + '\' , n - 1, 1) = '\' AND 
        CharIndex('\' , '\' + FilePath+ '\' , n) - n > 0
  )P
PIVOT 
   (MAX(FolderName) FOR RowNum IN 
    ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10])
    ) UP
OPTION (MAXRECURSION 1000)-- set this to the maximum length of your file path


-- Clean up
DROP TABLE #FilePath

【讨论】:

    【解决方案3】:

    一种方式(重复数据删除):

    ;with T(ordinal, path, starts, pos) as (
        select 1, path, 1, charindex('\', path) from #tbl
        union all
        select ordinal + 1, path, pos + 1, charindex('\', path, pos + 1)
        from t where pos > 0
    )
    select [1],[2],[3],[4],[5],[6],[7],[8],[9],[10] from (
        select 
            ordinal, path, substring(path, starts, case when pos > 0 then pos - starts else len(path) end) token
        from T
    ) T2
    pivot (max(token) for ordinal in ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10])) T3
    

    【讨论】:

      猜你喜欢
      • 2018-04-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-29
      • 1970-01-01
      • 2018-01-15
      相关资源
      最近更新 更多