【问题标题】:Extract data between characters SQL提取字符之间的数据 SQL
【发布时间】:2022-01-06 14:58:16
【问题描述】:

我正在尝试检索字符之间的随机数据

数据示例:

ABC-33-Ha8o89-00
ABC-232-Ui7380-000

在上面的例子中,我正在尝试获取 Ha8o89 和 Ui7380。基本上是左侧两划线和右侧一划线之后的任何数据。

【问题讨论】:

  • 您使用的是哪个数据库提供商?
  • @arutar 是 SQL Server。
  • 你试过什么?是否总是正好是三个破折号?如果没有破折号、一个破折号、两个破折号或四个+,您希望结果是什么?
  • @AaronBertrand 我尝试了子字符串方法,在该方法中我尝试定义从左边多少个空格开始我想从 x 个字符中提取值 select SUBSTRING(column, 8,6)作为表中的“字段”这就是为什么我正在为破折号方法寻求帮助。这种方法的问题是,提取之前或提取之后的字符数量可能会有所不同,即 whs,它始终是 3 个破折号。 2 之前和 1 之后
  • 您显然不能使用空格数/字符数,因为组件不是固定大小的。你看过CHARINDEX吗?桌子有钥匙吗?我的其他问题(多少破折号)的答案是什么?您使用的是什么版本的 SQL Server?

标签: sql sql-server character extract


【解决方案1】:

鉴于此数据:

CREATE TABLE dbo.RandomData(StringValue varchar(128));

INSERT dbo.RandomData(StringValue) VALUES
('ABC-33-Ha8o89-00'),
('ABC-232-Ui7380-000');

鉴于您声明总是三个破折号,这是一种快速而肮脏的方式:

SELECT StringValue,
       Parsed = PARSENAME(REPLACE(StringValue,'-','.'), 2) 
       -- parsename starts right
  FROM dbo.RandomData;

2016+,你可以使用OPENJSON

SELECT r.StringValue, Parsed = j.value
  FROM dbo.RandomData AS r
  CROSS APPLY OPENJSON ('["' 
    + REPLACE(r.StringValue, '-', '","') + '"]') AS j
  WHERE [key] = 2; -- keys are 0-based

在任何版本上,您都可以使用有序拆分函数(那里有几十个示例),这是我从this articlethis earlier answer 中获取的一个:

CREATE FUNCTION dbo.SplitOrdered
(
    @list    nvarchar(max), 
    @delim   nvarchar(10)
)
RETURNS TABLE 
WITH SCHEMABINDING 
AS 
RETURN
(
  WITH w(n) AS (SELECT 0 FROM (VALUES (0),(0),(0),(0)) w(n)),
       k(n) AS (SELECT 0 FROM w a, w b),
       r(n) AS (SELECT 0 FROM k a, k b, k c, k d, k e, k f, k g, k h),
       p(n) AS (SELECT TOP (COALESCE(LEN(@list), 0)) 
                ROW_NUMBER() OVER (ORDER BY @@SPID) -1 FROM r),
       spots(p) AS 
       (
         SELECT n FROM p 
         WHERE (SUBSTRING(@list, n, LEN(@delim + 'x') - 1) LIKE @delim OR n = 0)
       ),
       parts(p,val) AS 
       (
         SELECT p, SUBSTRING(@list, p + LEN(@delim + 'x') - 1, 
           LEAD(p, 1, 2147483647) OVER (ORDER BY p) - p - LEN(@delim)) 
         FROM spots AS s
       )
       SELECT listpos = ROW_NUMBER() OVER (ORDER BY p), 
              Item    = LTRIM(RTRIM(val))
         FROM parts
);

那么查询是:

SELECT r.StringValue, Parsed = s.Item
  FROM dbo.RandomData AS r
  CROSS APPLY dbo.SplitOrdered(r.StringValue, '-') AS s
  WHERE s.listpos = 3; -- listpos is 1-based

db<>fiddle 中的所有三个示例。

【讨论】:

    【解决方案2】:

    您可以在CROSS APPLY (VALUES 中使用CHARINDEX 来搜索第一个连字符,然后再次输入它以获取下一个连字符,依此类推。然后您只需使用SUBSTRING 即可获得正确的值。

    使用NULLIF 确保在找不到连字符时不会出错

    SELECT
      *,
      ThirdValue = SUBSTRING(d.StringValue, v2.Dash2 + 1, v3.Dash3 - v2.Dash2 - 1)
    FROM dbo.RandomData d
    CROSS APPLY (VALUES( NULLIF(CHARINDEX('-', d.StringValue), 0) )) v1(Dash1)
    CROSS APPLY (VALUES( NULLIF(CHARINDEX('-', d.StringValue, v1.Dash1 + 1), 0) )) v2(Dash2)
    CROSS APPLY (VALUES( NULLIF(CHARINDEX('-', d.StringValue, v2.Dash2 + 1), 0) )) v3(Dash3);
    

    db<>fiddle

    【讨论】:

      猜你喜欢
      • 2021-08-30
      • 2019-07-21
      • 1970-01-01
      • 1970-01-01
      • 2021-06-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多