【问题标题】:Retrieve the first substring with numbers? [closed]用数字检索第一个子字符串? [关闭]
【发布时间】:2020-03-06 17:14:44
【问题描述】:

我正在尝试检索带有数字的列的第一个子字符串(以空格作为分隔符)。

例子是

  1. 从“Volvo L90H Pye No2”获取“L90H”

  2. 从“Vio55-6B Pipeline Civil”中获取“Vio55-6B”

【问题讨论】:

  • 请向我们展示您的尝试。
  • 分而治之——学生应该学习的东西。简单的搜索将找到一个保留顺序的拆分器函数。这似乎是第一步——将你的价值观分开。一旦你有了它,你就可以过滤值包含数字的行。查看 LIKE 的文档以了解模式匹配能力。
  • 您使用的是什么版本的 SQL Server?这很重要,因为较新版本中有一些对您有用的功能(例如STRING_SPLIT
  • @Isaac, STRING_SPLIT() 不保留订单...

标签: sql-server tsql split pattern-matching sql-server-2016


【解决方案1】:

您可以string_split 您的值,然后选择带有数字的行。像这样。

declare @tbl table(id int,detail nvarchar(100))
insert @tbl(id,detail) values
(1,'Volvo L90H Pye No2'),(2,'Vio55-6B Pipeline Civil')

;with cte as (
select id,value,ROW_NUMBER() over(partition by id order by id) rn
from @tbl
cross apply string_split(detail,' ')
where value like '%[0-9]%'
)
select * from cte
where rn=1

【讨论】:

  • 来自String_Split:“输出行可能是任何顺序。顺序保证与输入字符串中子字符串的顺序匹配。”跨度>
  • 这个答案有效,但这种方法绝对危险。我刚刚添加了一个位置安全的方法...
【解决方案2】:

您可能想试试这个。使用string_split函数和patindex

with cte as (
    select 'Volvo L90H Pye No2' as val
    union
    select 'Vio55-6B Pipeline Civil') 
    select max(t.rn), t.value, t.val 
    from
        (select row_number() over(partition by val order by (select null)) rn, t2.value, t1.val
        from cte t1
        cross apply string_split(t1.val, ' ') t2
        where  patindex('%[0-9]%', t2.value) > 0) t
    where t.rn = 1
    group by t.val, t.value

输出:

【讨论】:

  • 与其他STRING_SPLIT() 答案相同的方法... 这绝对是危险的,因为STRING_SPLIT() 可能不会按预期顺序返回片段。我刚刚添加了一个位置安全的答案。
【解决方案3】:

接受的答案使用STRING_SPLIT()。这表明,您至少使用的是 v2016。重要的是要知道,STRING_SPLIT() 是垃圾(在大多数情况下),因为它可能不会以预期的顺序返回片段。最糟糕的是:这几乎永远有效。它会通过你所有的内部测试,但有一天它会在生产中部署后产生愚蠢的错误。

STRING_SPLIT() 是在 v2016 中引入的,JSON 支持也是如此。检查以下解决方案以找到位置安全的拆分器:

DECLARE @tbl TABLE(ID INT IDENTITY,YourString VARCHAR(100))
INSERT INTO @tbl VALUES
('Volvo L90H Pye No2'),('Vio55-6B Pipeline Civil');

WITH Numbered AS
(
    SELECT t.ID
          ,t.YourString
          ,A.*
          ,ROW_NUMBER() OVER(PARTITION BY t.ID ORDER BY A.[key]) AS RowNumber
    FROM @tbl t
    CROSS APPLY OPENJSON(CONCAT('["',REPLACE(t.YourString,' ','","'),'"]')) A
    WHERE A.[value] LIKE '%[0-9]%'
)
SELECT ID
      ,YourString
      ,[value] AS FirstFragmentWithNumber
FROM Numbered
WHERE RowNumber=1;

简而言之:我们使用简单的字符串方法将您的字符串转换为 JSON 数组。

a b c   =>   ["a","b","c"]

OPENSJON 将读取此数组并返回其value 列中的所有项目,而key 列将携带每个项目的位置。
ROW_NUMBER()PARTITION BY 一起使用将用1 标记每个ID 的每个第一 行。我们可以在最终的WHERE 中使用它。

【讨论】:

    猜你喜欢
    • 2020-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多