C# 替换列中的多个字符串元素

C# 替换列中的多个字符串元素,c#,sql-server,vb.net,ssis,C#,Sql Server,Vb.net,Ssis,我正在尝试清除SQL server数据库中的一列文本(如果有必要,请在Azure中) 文本包含了人们的名字,有很多词缀(博士、教授、医学博士、博士、硕士),还有很多我不想要的可疑字符 我想从这些行中去除很多东西——通常在一个字段中多次——因此我认为最好的方法是将它们添加到一个表中,并使用它遍历并用一个空格替换每一行,然后最终修剪并用一个空格替换多个空格,就像嵌套替换公式所示当我把我需要从专栏中删除的所有术语的1/3都放出来的时候,真是疯了 最后-我想要的输出是把名字分成第一个名字,中间的名字,姓

我正在尝试清除SQL server数据库中的一列文本(如果有必要,请在Azure中)

文本包含了人们的名字,有很多词缀(博士、教授、医学博士、博士、硕士),还有很多我不想要的可疑字符

我想从这些行中去除很多东西——通常在一个字段中多次——因此我认为最好的方法是将它们添加到一个表中,并使用它遍历并用一个空格替换每一行,然后最终修剪并用一个空格替换多个空格,就像嵌套替换公式所示当我把我需要从专栏中删除的所有术语的1/3都放出来的时候,真是疯了

最后-我想要的输出是把名字分成第一个名字,中间的名字,姓氏。所有的名字都很好,干净,没有其他信息

到目前为止,我一直在SSIS中处理数据,并探索了标准的T-SQL转换(使用nested replace(),但其增长如此之快,令人讨厌)。我已经探索了派生列-嵌套替换似乎是这里唯一现实的选择!?我终于尝试使用脚本化组件找到解决方案,但作为一名业余爱好者,我无法理解如何使用它,也没有找到任何示例

效率也是一个问题,因为我最初需要处理大约800000个姓名


我非常感谢在这件事上的任何帮助,因为我已经搜索了很长时间,但没有找到任何直接的帮助。

这只解决了问题的一部分,但是,我想详细说明一下分名这一点。我不希望这里有voets,但评论不会提供空间

首先,“最后-我想要的输出是把名字分成第一个名字,中间的名字,姓氏。所有的名字都很干净,没有其他信息。”这不会发生。名字有太多的变化。读一下,这可能看起来很傻,但这是真的

例如,假设一个名字被分成几个部分,用空格分隔。第一部分是标题,第二部分是名字,最后一部分是姓氏,中间的任何东西都是中间名。举这些例子:

Mr John Smith
Mrs Jane Alice Wallis Smith
Mr Dick van Dyke
Sarah Brown
显然,首先,对于第一个人,“约翰”是他的名字,“史密斯”是姓,先生是头衔。第二个人呢?沃利斯是中间名吗?如果可能是双筒姓(你怎么知道?),那么最后一个人呢?“范·戴克”是完整的姓氏。然后你有最后一个条目,标题甚至不见了;那里发生了什么


就像我说的,你不能用SQL来拆分一个名字。你必须有一些非常聪明的机器学习工具来做到这一点。

兔子洞,挑战将全名存储在一个字段中,然后在t-SQL中解析它,所有的免责声明都放在一边

清理数据,尤其是text/varchar/nvarchar列是一项挑战,不管上面提到的是什么,因为您发现嵌套替换可能会失控,并且难以管理

在t-sql中,您可以做一些事情来帮助您完成所要完成的任务。所有这些都需要对数据进行多次传递。我认为这可以分为两类清理。1-删除定义的单词,2-特殊字符

  • 把“单词”,在你的案例名称前缀和后缀中,放入一个你想去掉的表格中
  • 基本上去掉所有非字母字符
如果我的名字前缀或后缀是“Dean”或“Miss”或…而名字是“Dean Smith”或“Missy”或…,是的,就是这样,rabbit hole。放在一边,下面是一些示例代码,您可以尝试一下

--Test table for words I want to strip out.
DECLARE @WordsToRemove TABLE
    (
        [word] NVARCHAR(200)
    );

--Test table for my data I want to clean
DECLARE @TestData TABLE
    (
        [Data] NVARCHAR(500)
      , [CleanData] NVARCHAR(500)
    );

--Flag I am using to keep my while loops going
DECLARE @Continue INT;


--Insert of the words I want to remove.
INSERT INTO @WordsToRemove (
                         [word]
                     )
VALUES ( 'DR' )
     , ( 'D.R.' )
     , ( 'M.D.' )
     , ( 'md' )
     , ( 'Prof.' );

--Insert test names to clean.  I have a while loop here, was loading my test table with 10000+ recrods to see performance.
--You can leave the while loop here commented out just to see how the code works.  I got under 2 minutes for 100000+ records.  Your mileage may vary.
--WHILE (SELECT COUNT(*) FROM   @TestData) < 100000
    --BEGIN
        INSERT INTO @TestData (
                              [Data]
                          )
        VALUES ( N'DR Jimmy Smith' )
             , ( 'D.R. John Jones M.D.' )
             , ( 'Timothy Neal DR md' )
             , ( 'Prof. Bob Smith Dr M.D.' )
             , ( 'Taco;,,; Johns Dr. Prof.' )
             , ( 'Prof. ''#%^Special Charaters;,,; Dr. Prof.' );
    --END;

--Just updating a another column so I can save original state
UPDATE @TestData
SET    [CleanData] = [Data]


--Join to my @WordsToRemove table using PATINDEX, continue doing that until all occurrences have been removed.
--Clean out words we dont want
SET @Continue = 1;
WHILE @Continue = 1
    BEGIN
        SET @Continue = 0;
        UPDATE     [a]
        SET        [a].[CleanData] = REPLACE([a].[CleanData], [b].[word], '')
                 , @Continue = 1
        FROM       @TestData [a]
        INNER JOIN @WordsToRemove [b]
            ON PATINDEX('%' + [b].[word] + '%', [a].[CleanData]) > 0;
    END;

--Remove all non-alpha characters, preserving spaces
--PATINDEX using "%[^a-z ]%" looks of anything not a character and not a space.
SET @Continue = 1;
WHILE @Continue = 1
    BEGIN
        SET @Continue = 0;
        UPDATE [a]
        SET    [a].[CleanData] = STUFF([a].[CleanData], PATINDEX('%[^a-z ]%', [a].[CleanData]), 1, '')
             , @Continue = 1
        FROM   @TestData [a]
        WHERE  PATINDEX('%[^a-z ]%', [a].[CleanData]) > 0;
    END;

SELECT *
FROM   @TestData;
——我想去掉的单词的测试表。
声明@WordsToRemove表
(
[文字]NVARCHAR(200)
);
--我要清理的数据的测试表
声明@TestData表
(
[数据]NVARCHAR(500)
,[CleanData]NVARCHAR(500)
);
--我用来保持循环运行的标志
声明@Continue INT;
--插入我要删除的单词。
插入@WordsToRemove(
[字]
)
值('DR')
,(“D.R.”)
,(“医学博士”)
,(“md”)
,(“教授”);
--插入要清理的测试名称。我在这里有一个while循环,加载了10000多个recrods的测试表以查看性能。
--你可以在这里把while循环注释掉,看看代码是如何工作的。我用了不到2分钟的时间记录了100000多条记录。你的里程数可能会有所不同。
--而(从@TestData中选择COUNT(*)<100000
--开始
插入到@TestData中(
[数据]
)
价值观(N'DR Jimmy Smith')
,(“D.R.约翰·琼斯医学博士”)
,(“Timothy Neal博士”)
,(“鲍勃·史密斯教授医学博士”)
,('Taco;,,;约翰博士教授)
,(“Prof.”特殊字符;,,;Dr.Prof.);
--结束;
--只是更新另一列,以便保存原始状态
更新@TestData
设置[CleanData]=[Data]
--使用PATINDEX连接到my@WordsToRemove表,继续这样做,直到删除所有出现的内容。
--清除我们不想要的单词
设置@Continue=1;
而@Continue=1
开始
设置@Continue=0;
更新[a]
设置[a].[CleanData]=替换([a].[CleanData],[b].[word],“”)
,@Continue=1
来自@TestData[a]
内部连接@WordsToRemove[b]
在PATINDEX上('%'+[b].[word]+'%',[a].[CleanData])>0;
结束;
--删除所有非字母字符,保留空格
--使用“%[^a-z]%”的PATINDEX看起来像任何东西,而不是字符和空格。
设置@Continue=1;
而@Continue=1
开始
设置@Continue=0;
更新[a]
集合[a].[CleanData]=STUFF([a].[CleanData],PATINDEX('%[^a-z]]',[a].[Cl]