【问题标题】:Extract right of 2nd occurrence of character in string提取字符串中第二次出现的字符的权利
【发布时间】:2020-11-10 16:48:59
【问题描述】:

我使用的是 SQL Server 2014。

我有一个表,其中包含一个名为“addr”的字段,其中包含如下字符串值:

ROOM 1 101 My Street; My Town
ROOM 2 101 My Street; My Town
ROOM A 123 My Crescent; My Old Town
ROOM A 12a My Avenue; My Very Old Town

我需要做两件事:

  1. 提取第二个''和第三个''之间的数字 结果:
101
101
123
12a
  1. 提取第 3 个 ' ' 之后的文本,直到第一个 ';'结果:
My Street
My Street
My Crescent
My Avenue

我该怎么做?

我试过了:

SELECT CAST('<x>' + REPLACE(addr, ' ', '</x><x>') + '</x>' AS XML).value('/x[1]', 'varchar(200)') from mytable;

但这会导致“房间”。

更新:

为了提取第 2 和第 3 之间的数字,我使用了以下方法:

SELECT CAST('<x>' + REPLACE(addr, ' ', '</x><x>') + '</x>' AS XML).value('/x[3]', 'varchar(200)') from MyTable;

如何从第三个''和第一个';'中提取不过呢?

【问题讨论】:

  • 使用支持序数位置的字符串拆分器(我推荐DelimitedSplit8K_LEAD),这很简单。
  • @Larnu 我不确定我是否完全理解 - 这是一个 SQL 函数吗?
  • 如果您想在一个 select 语句中全部完成,您可以使用 CHARINDEXSUBSTRING 的可怕组合。像select SUBSTRING(addr, charindex(' ', addr, charindex(' ', addr, 1) + 1) + 1,charindex(' ', addr, charindex(' ', addr, charindex(' ', addr, 1) + 1) + 1) - charindex(' ', addr, charindex(' ', addr, 1) + 1) -1) 这样的东西会让你的号码在第二个和第三个''之间。
  • @Michael, select SUBSTRING(addr,charindex(' ', addr, charindex(' ', addr, charindex(' ', addr, 1) + 1) + 1) + 1,charindex(';', addr, 1) - charindex(' ', addr, charindex(' ', addr, charindex(' ', addr, 1) + 1) + 1) -1) 将在第三个 ' ' 和第一个 ';' 之间执行。就像我说的那样,这非常可怕,并且严格依赖于空间等。在每条记录中都处于完全相同的位置。

标签: sql-server string tsql substring charindex


【解决方案1】:

由 cmets 中的 Joe J 回答:

如果您想在一个 select 语句中完成所有操作,您可以使用 CHARINDEX 和 SUBSTRING 的可怕组合。像这样的

select SUBSTRING(addr, charindex(' ', addr, charindex(' ', addr, 1) + 1) + 1,charindex(' ', addr, charindex(' ', addr, charindex(' ', addr, 1) + 1) + 1) - charindex(' ', addr, charindex(' ', addr, 1) + 1) -1) 

将在第 2 和第 3 ' ' 之间获取您的号码。

感谢@JoeJ - 我如何修改它以从第 3 个 ' ' 到第一个 ';' ? ——迈克尔

@迈克尔,

select SUBSTRING(addr,charindex(' ', addr, charindex(' ', addr, charindex(' ', addr, 1) + 1) + 1) + 1,charindex(';', addr, 1) - charindex(' ', addr, charindex(' ', addr, charindex(' ', addr, 1) + 1) + 1) -1) will do between the third ' ' and the first ';'. 

就像我说的那样,这非常可怕,并且严格依赖于空格等。在每条记录中完全相同的位置。

【讨论】:

    【解决方案2】:

    如果您的要求不会随着时间的推移发生太大变化,您可以像这样以非常严格的方式对其进行编程:

    with t as  (
    select 'ROOM 1 101 My Street; My Town' a union all
    select 'ROOM 2 101 My Street; My Town' a union all
    select 'ROOM A 123 My Crescent; My Old Town' a union all
    select 'ROOM A 12a My Avenue; My Very Old Town' a )
    , t2 as (
    select a, PATINDEX('% %', a) pi1, 
              PATINDEX('% %', SUBSTRING(a, 1 + nullif(PATINDEX('% %', a), 0), LEN(a))) pi2, 
              PATINDEX('% %', SUBSTRING(a, 1 + PATINDEX('% %', SUBSTRING(a, 1 + nullif(PATINDEX('% %', a), 0), LEN(a))) + nullif(PATINDEX('% %', a), 0), LEN(a))) pi3,
              PATINDEX('%;%', SUBSTRING(a, 1 + PATINDEX('% %', SUBSTRING(a, 1 + PATINDEX('% %', SUBSTRING(a, 1 + nullif(PATINDEX('% %', a), 0), LEN(a))) + nullif(PATINDEX('% %', a), 0), LEN(a))) + PATINDEX('% %', SUBSTRING(a, 1 + nullif(PATINDEX('% %', a), 0), LEN(a))) + nullif(PATINDEX('% %', a), 0), LEN(a))) pi4
      from t
    )
    select a, SUBSTRING(a, pi1, pi2) s1, SUBSTRING(a, pi1 + pi2, pi3) s2, SUBSTRING(a, pi1 + pi2 + pi3, pi4) s3, SUBSTRING(a, pi1 + pi2 + pi3 + pi4, len(a)) s4
     from t2
    

    然后它返回:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-02-26
      • 2018-02-05
      • 1970-01-01
      • 2016-07-25
      • 1970-01-01
      • 2017-05-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多