【问题标题】:SQL to ONLY Extract Single Word or Number after a Keyword in StringSQL 仅在字符串中的关键字之后提取单个单词或数字
【发布时间】:2022-01-07 23:35:15
【问题描述】:
SELECT 
 NOTE_ID    
,NOTE_DATE  
,NOTE_TEXT  
FROM NOTE.dbo.NOTE_TABLE

从上面的简单查询,我得到:

NOTE_ID NOTE_DATE NOTE_TEXT
54876 2020-10-12 Purpose: Traveling Salesman Visit Customer Name: John Doe Date Account
Opened: 6/8/19 Customer Address: 428 S. Palm Tree Lane Lokey AZ 85546 Primary
Account Rep: Hank Stank Customer Account #: 1234567 Customer Preferred
Contact Time: Evenings Customer Owns/Rents: Owns Customer Employed: Yes
Customer Military Discount: No Customer Returns: No

我希望能够仅提取客户帐户 #“1234567”(或者如果它为 null/“UNKNOWN” - 客户帐户 # 之后和客户首选联系时间之前的任何内容。我尝试了各种子字符串函数来获取客户帐户 #,但无法删除之后的所有内容。任何建议将不胜感激。

请注意,NOTE_TEXT 字段都在一行上。不知道为什么它显示在多行上。

【问题讨论】:

    标签: sql replace substring


    【解决方案1】:

    对于复杂的字符串解析(SQL 确实不太擅长),我使用了 CROSS APPLY 的层,这样我一次可以找到一个。它确实帮助我跟踪每一层并逐步调试。

    DROP TABLE IF EXISTS #Note
    Create Table #Note (
        NOTE_ID INT PRIMARY KEY
        ,NOTE_DATE DATE
        ,NOTE_TEXT Varchar(1000)
    )
    
    INSERT INTO #Note
    Values(54876,'2020-10-12', 'Purpose: Traveling Salesman Visit Customer Name: John Doe Date Account Opened: 6/8/19 Customer Address: 428 S. Palm Tree Lane Lokey AZ 85546 Primary Account Rep: Hank Stank Customer Account #: 1234567 Customer Preferred Contact Time: Evenings Customer Owns/Rents: Owns Customer Employed: Yes Customer Military Discount: No Customer Returns: No')
    ,(62345,'2020-11-11', 'Customer Account #: 123 blah') /*Value at beginning of text*/
    ,(67890,'2021-02-28', 'Blah Customer Account #: 456') /*Value at end of text*/
    ,(99999,'2022-01-01', 'No matching account #') 
    
    
    
    DECLARE @SearchPhrase AS Varchar(20) = 'Customer Account #:';
    
    SELECT *
        ,AccountNumberParsedFromNote = SUBSTRING(NOTE_TEXT,B.IDX1,C.IDX2-B.IDX1)
    FROM #Note AS A
    CROSS APPLY (SELECT IDX1 = NULLIF(CHARINDEX(@SearchPhrase, NOTE_TEXT),0) + LEN(@SearchPhrase) + 1) AS B /*Index of letter after search phrase*/
    CROSS APPLY (SELECT IDX2 = CHARINDEX(' ',NOTE_TEXT + ' '/*Trailing space accounts for value at end of string*/,B.IDX1)) AS C /*Index of end of next word after search phrase*/ 
    

    【讨论】:

    • 谢谢你,Stephan - 效果很好!
    • 没问题,请将我的回答标记为已接受,以便其他人知道您的问题已得到回答
    【解决方案2】:

    我确信可能有更好的方法来做到这一点,但它应该匹配短语Customer Account #:

    DECLARE @searchPhrase AS CHAR(20) = 'Customer Account #: ';
    SELECT IIF(PhraseExists > 0, SUBSTRING(CustomerNumNextPhrase, 0, CHARINDEX(' ', CustomerNumNextPhrase)), 'UNKNOWN') AS Account
    FROM (SELECT CHARINDEX(@searchPhrase, NotesData) AS PhraseExists,
                 REPLACE(NotesData, SUBSTRING(NotesData, 0, CHARINDEX(@searchPhrase, NotesData) + 20), '') AS CustomerNumNextPhrase
          FROM test.dbo.Notes) A;
    

    如果找不到短语Customer Account #: ,则内部查询报告一个0,而在这种情况下,外部查询报告UNKNOWN。如果内部查询报告除 0 以外的任何内容,它会返回主字符串的子字符串,在该子字符串中它会切断 Customer Account #: 之前的所有内容以及 Customer Account #: 短语本身。然后外部查询获取下一个关键字的子字符串,直到下一个空格。

    【讨论】:

    • 感谢您的快速回复。我会对此进行测试,然后告诉你结果如何。
    猜你喜欢
    • 2020-10-28
    • 2021-11-11
    • 2021-07-04
    • 2019-10-18
    • 2015-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多