查询中包含多个 CHARINDEX 选项的 SUBSTRING

SUBSTRING with multiple CHARINDEX options in query

我试图仅从中提取姓氏的列具有可能的组合,如 H.NaudeH. NaudeH Naude,我只需要 Naude 部分.如果我使用 SUBSTRING 方法,我可以在 space 或点之后获取字符,但是如何测试所有 3 种可能性?不幸的是,此数据来自导入的条目表单,因此我无法控制数据的格式。目前我有以下内容仅适用于 space 字符

SUBSTRING(H.PtsNonFemale, CHARINDEX('' '', H.PtsNonFemale) +1, DATALENGTH(H.PtsNonFemale) - CHARINDEX('' '', H.PtsNonFemale) +1 ) AS Female

非常感谢任何帮助。

假设提供的数据涵盖所有 use-cases 那么您可以简单地按照要删除的组件的长度降序测试每种情况,并使用在子字符串中找到的第一个匹配项(最长)。

SELECT H.PtsNonFemale
    , SUBSTRING(H.PtsNonFemale, COALESCE(NULLIF(I.A,0)+6,NULLIF(I.B,0)+2,NULLIF(I.C,0)+1,NULLIF(I.D,0)+1), LEN(H.PtsNonFemale)) AS Female
FROM (
    VALUES
    ('H.Naude'), ('H. Naude'), ('H Naude'), ('A. M. Someone')
) H (PtsNonFemale)
CROSS APPLY (
    VALUES
    (PATINDEX('_. _. %', H.PtsNonFemale), CHARINDEX('. ',H.PtsNonFemale,0), CHARINDEX('.',H.PtsNonFemale,0), CHARINDEX(' ',H.PtsNonFemale,0))
) I (A, B, C, D);

Returns:

PtsNonFemale Female
H.Naude Naude
H. Naude Naude
H Naude Naude
A. M. Someone Someone

将一串标记标记化而不是解析要好得多。

SQL Server XQuery 可以很容易地做到这一点。

无需多次调用字符串函数SUBSTRING(), COALESCE(), NULLIF(), LEN(), PATINDEX(), CHARINDEX()等弹幕

SQL

-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, PtsNonFemale VARCHAR(100));
INSERT INTO @tbl (PtsNonFemale) VALUES
('H.Naude'),
('H. Naude'),
('H Naude'),
('A. M. Someone');
-- DDL and sample data population, end

DECLARE @separator CHAR(1) = '.';

SELECT t.*
    , c.value('(/root/r[last()]/text())[1]', 'VARCHAR(30)') AS Female
FROM @tbl AS t
CROSS APPLY (SELECT TRY_CAST('<root><r><![CDATA[' + 
        REPLACE(REPLACE(PtsNonFemale,SPACE(1),@separator), @separator, ']]></r><r><![CDATA[') + 
        ']]></r></root>' AS XML)) AS t1(c);

输出

+----+---------------+---------+
| ID | PtsNonFemale  | Female  |
+----+---------------+---------+
|  1 | H.Naude       | Naude   |
|  2 | H. Naude      | Naude   |
|  3 | H Naude       | Naude   |
|  4 | A. M. Someone | Someone |
+----+---------------+---------+

使用string_split():

select
  PtsNonFemale,
  (select top 1 value
   from string_split(PtsNonFemale, ' ', 1)
   order by ordinal desc) as Female
from mytable