【问题标题】:Extracting multiple values from string and ordering them从字符串中提取多个值并对它们进行排序
【发布时间】:2022-12-21 14:53:24
【问题描述】:

我在一个 Notes 字段中有一些值,这些值由这样的值组成,其中 abc 代表不同的词:

请求说明:VAR - abc abc abc abc abc

不幸的是,数据存储方式的设计非常糟糕,我需要为每个“Required Notes:”记录提取注释类型。它还需要从最近到最旧的顺序(字符串的最后一部分到字符串的第一部分)。

CREATE TABLE #TestData
(
    ClientID int,
    Notes varchar(8000)
)
insert into #TestData
(
    ClientID,
    Notes
)
select
    1,
    'Request Notes: VAR - abc abc abc abc abc'
union all
select
    2,
    'Request Notes: OZR - abc abc abc abc abc Request Notes: ACC - abc abc abc abc abc Request Notes: TYU - abc abc abc abc abc'
union all
select
    3,
    'Request Notes: TYU - abc abc abc abc abc Request Notes: VAR - abc abc abc abc abc'

这就是我期望上述示例的输出方式:

--Expected Output

Client ID       Type    Order
1               VAR     1
2               TYU     1
2               ACC     2
2               OZR     3
3               VAR     1
3               TYU     2

到目前为止,我把它放在一起提取 OZR,但我对如何获取其他列表并将列表排序到上面的预期输出中感到困惑。

DECLARE @Text varchar(500) = 'Request Notes: OZR - abc abc abc abc abc Request Notes: ACC - abc abc abc abc abc Request Notes: TYU - abc abc abc abc abc'

SELECT TRIM(REPLACE(REPLACE(SUBSTRING(@Text, CHARINDEX(':', @Text), CHARINDEX('-',@text) - CHARINDEX(':', @Text) + Len('-')),':',''),'-',''))

【问题讨论】:

    标签: sql sql-server tsql sql-server-2017


    【解决方案1】:

    您可以使用打开json将数据提取为数组并进行过滤:

    select d.ClientId, n.*
    from #testdata d
    cross apply (
      select 
        Left(j.[value],3) [Type],
        Row_Number() over(order by Convert(int,j.[key])) [Order] 
      from OpenJson(Concat('["',replace(notes,'Notes: ', '","'),'"]')) j
      where j.[value] != 'Request'
     )n;
    

    例子Fiddle

    【讨论】:

      【解决方案2】:

      这是递归 CTE 版本。它根据查找“Request Notes:”拆分字符串,然后进行左/右组合以提取 3 个字母的代码。它在构建时迭代订单。然后您从 CTE 中选择并只获取有一些 NotesRemainder 的行:

      ;
      WITH CTESplit
      AS (
          SELECT ClientID,
                 RIGHT(LEFT(Notes, CHARINDEX('Request Notes:', Notes) + 17), 3) AS NotesPart,
                 RIGHT(Notes, LEN(Notes) - CHARINDEX('Request Notes:', Notes) - 17) AS NotesRemainder,
                 1 AS [Order]
          FROM #TestData
          WHERE Notes IS NOT NULL AND CHARINDEX('Request Notes:', Notes) > 0
          UNION ALL
          SELECT CTESplit.ClientID,
                 RIGHT(LEFT(CTESplit.NotesRemainder, CHARINDEX('Request Notes:', CTESplit.NotesRemainder) + 17), 3),
                 RIGHT(CTESplit.NotesRemainder, LEN(CTESplit.NotesRemainder) - CHARINDEX('Request Notes:', CTESplit.NotesRemainder)),
                 CTESplit.[Order] + 1
          FROM CTESplit
          WHERE CTESplit.NotesRemainder IS NOT NULL AND CHARINDEX('Request Notes:', CTESplit.NotesRemainder) > 0
          UNION ALL
          SELECT CTESplit.ClientID,
                 RIGHT(LEFT(CTESplit.NotesRemainder, CHARINDEX('Request Notes:', CTESplit.NotesRemainder) + 17), 3),
                 NULL,
                 CTESplit.[Order] + 1
          FROM CTESplit
          WHERE CTESplit.NotesRemainder IS NOT NULL AND CHARINDEX('Request Notes:', CTESplit.NotesRemainder) = 0
      )
      SELECT CTESplit.ClientID,
             CTESplit.NotesPart AS Type,
             CTESplit.[Order]
      FROM CTESplit
      WHERE CTESplit.NotesRemainder IS NOT NULL
      ORDER BY CTESplit.ClientID,
               CTESplit.[Order] DESC;
      

      【讨论】:

        猜你喜欢
        • 2018-11-13
        • 2021-08-16
        • 2020-06-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-14
        • 2016-04-20
        • 1970-01-01
        相关资源
        最近更新 更多