【问题标题】:Substring from a String in SQL Server after a symbol to the end of the field if the symbol exists如果符号存在,则从 SQL Server 中的字符串在符号之后到字段末尾的子字符串
【发布时间】:2021-05-10 17:34:45
【问题描述】:

我已查询 ReportServer 数据库中的目录以获取报表服务器中存在的文件夹列表。所以我的结果如下所示:

[Path]
/Admin
/Compliance/Self Serve/Dublin
/Directors/Daily Reports

因此,顶级文件夹可以有一个正斜杠,顶级文件夹可以有两个正斜杠,向下一级,然后是更深的文件夹级别的 3 个或更多。

我需要把它分成两部分。第一列应该只是没有起始正斜杠的顶级文件夹名称,第二部分应该是下一层文件夹结构的其余部分,例如

[Folder]         [Subfolders]
Admin            
Compliance       Self Serve/Dublin
Directors        Daily Reports

有很多方法可以在符号之前和之后获取字符串,这些方法可以满足我的需要,但是顶级文件夹的问题让我很困惑,那里只有一个正斜杠。

所有建议都拼命地收到了。

【问题讨论】:

    标签: sql-server string uisplitviewcontroller


    【解决方案1】:

    请尝试以下解决方案。

    它基于tokenization的思想。

    • 第一个标记(XPath 谓词[1])将是根文件夹。
    • 其余的标记(XPath 谓词[position() gt 1])是子文件夹。

    SQL

    -- DDL and sample data population, start
    DECLARE @tbl TABLE  (ID INT IDENTITY PRIMARY KEY, [path] NVARCHAR(MAX));
    INSERT INTO @tbl (path) VALUES
    ('/Admin'),
    ('/Compliance/Self Serve/Dublin'),
    ('/Directors/Daily Reports'),
    ('//Directors/Daily Reports/Monday/Tuesday');
    -- DDL and sample data population, end
    
    DECLARE @separator CHAR(1) = '/';
    
    WITH rs AS
    (
        SELECT * 
            , TRY_CAST('<root><x><![CDATA[' + 
              REPLACE([path], @separator, ']]></x><x><![CDATA[') + 
              ']]></x></root>' AS XML) AS xmldata
        FROM @tbl
    )
    SELECT ID, [Path]
        , xmldata.value('(/root/x[text()][1]/text())[1]', 'NVARCHAR(100)') AS [Folder] 
        , REPLACE(xmldata.query('
            for $x in /root/x[text()][position() gt 1]
            return if ($x is (/root/x[position() = last()])[1]) then data($x)
                else concat($x, sql:variable("@separator"))
        ').value('text()[1]', 'NVARCHAR(MAX)'), '/ ', '/') AS [Subfolders]
    FROM rs;
    

    输出

    +----+------------------------------------------+------------+------------------------------+
    | ID |                   Path                   |   Folder   |          Subfolders          |
    +----+------------------------------------------+------------+------------------------------+
    |  1 | /Admin                                   | Admin      | NULL                         |
    |  2 | /Compliance/Self Serve/Dublin            | Compliance | Self Serve/Dublin            |
    |  3 | /Directors/Daily Reports                 | Directors  | Daily Reports                |
    |  4 | //Directors/Daily Reports/Monday/Tuesday | Directors  | Daily Reports/Monday/Tuesday |
    +----+------------------------------------------+------------+------------------------------+
    

    【讨论】:

    • 这是完美的谢谢。这对我来说是一个新的学习水平(我以前没有像这样进行过任何适当的 XML 查询),但我已经能够将其余列夹在其中并让拆分完美地工作!
    【解决方案2】:

    我会保证目录名称的结尾带有“/”字符,这样您就可以选择简单的解决方案(如 SUBSTRING + CHARINDEX)。

    例子:

    DECLARE @SEP VARCHAR(1) = '/'
    DECLARE @CATALOG TABLE ( [Path] VARCHAR(200) )
    
    INSERT INTO @CATALOG ([Path]) 
    VALUES  ('/Admin'),
            ('/Compliance/Self Serve/Dublin'),
            ('/Directors/Daily Reports'),
            ('//Directors/Daily Reports/Monday/Tuesday')
    
    UPDATE @CATALOG SET [Path] = REPLACE([Path], '//', '/') + @SEP -- At least one "/" at the end of the directory.
    
    SELECT          
        SUBSTRING([Path], 2, CHARINDEX(@SEP, [Path], 2) -2)         AS Folder,
        SUBSTRING([Path], CHARINDEX(@SEP, [Path], 2) + 1, LEN([Path]) - IIF(LEN([Path]) > CHARINDEX(@SEP, [Path], 2) +1, CHARINDEX(@SEP, [Path], 2) +1, CHARINDEX(@SEP, [Path], 2) ) )  AS Subfolders
    FROM @CATALOG
    

    【讨论】:

    • (1) 如果您需要UPDATE 实际表才能查询它,这是一种有缺陷的方法。 (2) 对于 "...顶级文件夹的两个正斜杠...".,建议的实现将失败
    • 哎呀!谢谢。 (1) 您可以使用临时表进行转换。 (2) 为“两个正斜杠”添加了替换。
    • *(1) 或者将 SELECT 查询中的 [Path] 替换为 UPDATE 值。
    猜你喜欢
    • 2014-12-04
    • 1970-01-01
    • 2011-10-25
    • 2012-07-23
    • 2022-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多