SQL 仅提取字符串中关键字后的单个单词或数字
SQL to ONLY Extract Single Word or Number after a Keyword in String
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”(或者如果它为空/“未知”-客户帐户#之后和客户首选联系时间之前的任何内容。我已经尝试了各种子字符串函数来进入客户帐号#,但无法删除其后的所有内容。如有任何建议,我们将不胜感激。
请注意,NOTE_TEXT 字段全部在一行中。不确定为什么它显示为多行分解。
我确定可能有更好的方法来执行此操作,但它应该与短语 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 以外的任何内容,它会 returns 主字符串的子字符串,其中它会切断 Customer Account #:
之前的所有内容以及 Customer Account #:
短语本身。然后外部查询获取下一个关键字的子字符串,直到下一个 space.
对于复杂的字符串解析(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*/
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”(或者如果它为空/“未知”-客户帐户#之后和客户首选联系时间之前的任何内容。我已经尝试了各种子字符串函数来进入客户帐号#,但无法删除其后的所有内容。如有任何建议,我们将不胜感激。
请注意,NOTE_TEXT 字段全部在一行中。不确定为什么它显示为多行分解。
我确定可能有更好的方法来执行此操作,但它应该与短语 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 以外的任何内容,它会 returns 主字符串的子字符串,其中它会切断 Customer Account #:
之前的所有内容以及 Customer Account #:
短语本身。然后外部查询获取下一个关键字的子字符串,直到下一个 space.
对于复杂的字符串解析(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*/