【问题标题】:How to extract substrings from multiple delimiters like '\' in SQL Server 2014?如何从 SQL Server 2014 中的“\”等多个分隔符中提取子字符串?
【发布时间】:2019-10-22 15:26:20
【问题描述】:

我有一个像这样的字符串 '/1064_MyHoldings/ONLINE/Adhoc/Rpt_CompanyCodeElig' 我只想提取 '1064_MyHoldings' 就像这样有不同的字符串,我只想要前两个分隔符之间的字符串的第一部分?

select 
    left(Applications, Len(Path) - CHARINDEX('/', Applications) + 1) FolderName 
from 
    (select distinct 
         Substring(C.Path, CHARINDEX('/', C.Path) + 1, LEN(C.Path) - CHARINDEX('/', C.Path)) Applications) Result 

其中 Applications 是具有类似“/1064_MyHoldings/ONLINE/Adhoc/Rpt_CompanyCodeElig”的数据的列名

预期结果应该是“1064_MyHoldings”,它只是前两个“/”之间的字符串的第一部分

【问题讨论】:

  • 如果你能放更多的信息,比如源字符串是 xxxxx,期望的字符串是 yyy,这将有助于人们更好地理解你。
  • @Tim Biegeleisen 为问题添加了生动的描述
  • 您应该努力使用 SQL 中的规范化数据。由于许多原因,使用分隔字符串将多个不同的数据点存储在同一列、参数或变量中确实是一种不好的做法 - 请阅读它们here
  • @ZoharPeled 在某些用例中,将路径存储在数据库表中不一定是不好的做法。例如,它可能来自应用层(但是,在这种情况下,在应用层处理这个需求可能更有意义)。
  • @TimBiegeleisen 路径不是分隔字符串。诚然,没有将问题中的字符串识别为路径可能是我的错 - 但是路径是一个(复合)数据点。我说的不是这种情况。我说的是存储 1,2,3,4a/b/c/d 之类的东西,其中分隔字符串的每个部分都是一个“项目”。

标签: sql substring


【解决方案1】:

我们可以在这里利用基本字符串函数。例如,要查找前两个/ 中包含的子字符串,我们可以尝试:

WITH yourTable AS (
    SELECT '/1064_MyHoldings/ONLINE/Adhoc/Rpt_CompanyCodeElig' AS Path
)

SELECT
    CASE WHEN Path LIKE '%/%/%' THEN
    SUBSTRING(Path,
              CHARINDEX('/', Path) + 1,
              CHARINDEX('/', Path, CHARINDEX('/', Path) + 1) - CHARINDEX('/', Path) - 1)
         ELSE 'NA' END AS first_component
FROM yourTable;

Demo

使上述逻辑成为可能的原因是,对于第一个路径组件以及可能的任何组件,CHARINDEX 有一个可选的第三个参数,它允许我们指定搜索分隔符 / 的起始位置。

注意:如果您确定Path 的第一个字符总是只是一个/,那么您可以使用更简单的查询:

SELECT
    CASE WHEN Path LIKE '%/%/%'
         THEN SUBSTRING(Path, 2, CHARINDEX('/', Path, 2) - 2)
         ELSE 'NA' END AS first_component
FROM yourTable;

但是,如果您知道 / 是路径中的第一个字符,这只会再次起作用。否则,您将需要使用上面更详细的版本。

【讨论】:

  • 它抛出错误,因为“传递给 LEFT 或 SUBSTRING 函数的长度参数无效”。
  • @AditiSingh 这只能意味着您的某些字符串包含少于两个分隔符。
  • @AditiSingh Zohar 是正确的,并且很可能您至少有一个路径少于两个/。对于那些分隔符少于两个的路径,我更新了我的答案以返回 NA
  • @TimBiegeleisen 是的,有些字符串只有一个分隔符。
【解决方案2】:

一种基于 Tim 的答案的丑陋但可能更灵活的方法,您可以在其中指定您想要的字符串的哪一部分。 我更新了此解决方案以处理可能不以分隔符开头的字符串。

with cte1 as (select '1064_MyHoldings/' as Path)

,cte2 as (select case when left(Path,1)<>'/' then  '/'+ Path else Path end as Path from cte1)

select  case when Path like '%/%/%'
         then cast('<x>'+replace(Path,'/','</x><x>')+'</x>' as xml).value(N'/x[2]','varchar(50)')
         else right(Path,len(Path)-1) end as first_component
from cte2

x[2] 参数是您要更改的参数以获取字符串的不同部分。它以2 开头,因为您在字符串之前有一个分隔符。按照逻辑,x[3] 将为您提供“在线”示例字符串。 ELSE 未设置为“NA”,因为我认为当您的分隔符少于 2 个时您会想要字符串的第一个元素。

【讨论】:

  • @MeckelsDiverticulum 确实是一种灵活的方法
  • @AditiSingh 我对其进行了一些修改,因此它也适用于不以分隔符开头的字符串。
  • @MeckelsDiverticulum 这是一个令人惊叹的方法,非常感谢它已经解决了我所有即将到来的场景......我的未来已经排序感谢 Meck (:
猜你喜欢
  • 2021-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-27
  • 2018-02-05
  • 1970-01-01
  • 2014-01-05
  • 1970-01-01
相关资源
最近更新 更多