【问题标题】:MS SQL Server - replace names while avoiding words containing the namesMS SQL Server - 替换名称,同时避免包含名称的单词
【发布时间】:2020-03-12 01:07:05
【问题描述】:

这是我第一次在 Stack Overflow 上发帖,如果我能做得更好或提供更多信息,请告诉我。

我这几天一直在研究这个问题。我有一张桌子,上面有员工关于公司的 cmets。其中一些可以指公司中的特定员工。出于人力资源方面的原因,我们希望将任何出现的员工姓名替换为“员工”一词。我们不考虑拼写错误或拼写错误。

我想要的结果的一个例子是:

Input: 'I dislike dijon mustard. My boss Jon sucks.'

Name to search for: 'Jon'

Output: 'I dislike dijon mustard. My boss employee sucks.'

另一个例子:

Input: 'Aggregating data is boring. Greg is the worst person ever.'

Name to search for: 'Greg'

Output: 'Aggregating data is boring. employee is the worst person ever.'


我想在 cmets 中搜索员工姓名的出现情况,但如果它们后面没有后面跟着其他字母或数字。应替换名称两端出现的空格或标点符号。

到目前为止,我已经尝试了以下线程中的建议:

How to replace a specific word in a sentence without replacing in substring in SQL Server 替换-in-substring-in-s

这产生了以下结果

update c
set c.Comment = rtrim(ltrim(Replace(replace(' ' + c.Comment + ' ',' ' + en.FirstName + ' ', 'employee'), ' ' + en.FirstName + ' ', 'employee')))
from AnswerComment c
join #EmployeeNames en on en.SurveyId = c.SurveyId
    and c.Comment like '%' + en.FirstName + '%'

但是,我得到了这样的结果:

Input: 'I hate bob.'

Name to search for: 'Bob'

Output: 'I hate bob.'


Input: 'Jon sucks'

Name to search for: 'Jon'

Output: 'employeesucks'


一位同事看了这个帖子Replace whole word using ms sql server "replace"

并据此给了我以下信息:

DECLARE @token VARCHAR(10) = 'bob';
DECLARE @replaceToken VARCHAR(10) = 'employee';

DECLARE @paddedToken VARCHAR(10) = ' ' + @token + ' ';
DECLARE @paddedReplaceToken VARCHAR(10) = ' ' + @replaceToken + ' ';
;WITH Step1 AS (
    SELECT CommentorId
         , QuestionId
         , Comment
         , REPLACE(Comment, @paddedToken, @paddedReplaceToken) AS [Value]
      FROM AnswerComment
     WHERE SurveyId = 90492
       AND Comment LIKE '%' + @token + '%'
), Step2 AS (
    SELECT CommentorId
         , QuestionId
         , Comment
         , REPLACE([Value], @paddedToken, @paddedReplaceToken) AS [Value]
      FROM Step1
), Step3 AS (
    SELECT CommentorId
         , QuestionId
         , Comment
         , IIF(CHARINDEX(LTRIM(@paddedToken), [Value]) = 1, STUFF([Value], 1, LEN(TRIM(@paddedToken)), TRIM(@paddedReplaceToken)), [Value]) AS [Value]
      FROM Step2
)
SELECT CommentorId
     , QuestionId
     , Comment
     , IIF(CHARINDEX(REVERSE(RTRIM(@paddedToken)), REVERSE([Value])) = 1, 
        REVERSE(STUFF(REVERSE([Value]), CHARINDEX(REVERSE(RTRIM(@paddedToken)), REVERSE([Value])), LEN(RTRIM(@paddedToken)), REVERSE(RTRIM(@paddedReplaceToken)))), 
        [Value])
  FROM Step3;

但我不知道如何实现这一点。

另一个我找不到的帖子建议使用%[^a-z0-9A-Z]% 进行搜索,如下所示:

update c
set c.Comment = REPLACE(c.Comment, en.FirstName, 'employee')
from AnswerComment c
join #EmployeeNames en on en.SurveyId = c.SurveyId
    and c.Comment like '%' + en.FirstName + '%'
    and c.Comment not like '%[^a-z0-9A-Z]%' + en.FirstName + '%[^a-z0-9A-Z]%'
select @@ROWCOUNT [first names replaced]

这对我不起作用。即使员工姓名是较大单词的一部分,它也会替换出现的员工姓名,如下例所示:

Input: 'I dislike dijon mustard.'

Name to search for: 'Jon'

Output: 'I dislike diemployee mustard.'


在这一点上,在我看来,这是不可能实现的。我实现这些的方式有什么问题,或者我遗漏了什么明显的东西吗?

【问题讨论】:

  • 这不适合你吗?声明 @input nvarchar(max) = '我不喜欢第戎芥末。我的老板乔恩很烂。 -- 要搜索的名称:'Jon' select replace(@input, 'Jon', 'employee ')

标签: sql sql-server replace


【解决方案1】:

这样的事情似乎行得通。

declare @charsTable table (notallowed char(1))
insert into @charsTable (notallowed) values (',')
insert into @charsTable (notallowed) values ('.')
insert into @charsTable (notallowed) values (' ')

declare @input nvarchar(max) = 'Aggregating data is boring. Greg is the worst person ever.'
declare @name nvarchar(50) = 'Greg'
--declare @input nvarchar(max) =  'I dislike dijon mustard. You know who sucks? My boss Jon.'
--declare @name nvarchar(50) = 'Jon'

select case when @name + notallowed = value or notallowed + @name = value or notallowed + @name = value then replace(value, @name, 'employee') else value end 'data()'  from string_split(@input, ' ')
left join @charsTable on @name + notallowed = value or notallowed + @name = value or notallowed + @name + notallowed = value
for xml path('')

结果:

聚合数据很无聊。员工是有史以来最糟糕的人。

我不喜欢第戎芥末。你知道谁烂吗?我的老板雇员。

【讨论】:

  • 但是可以有一个'.' (点)或“,”(逗号)直接在员工姓名之后!
  • 发送@Luuk。我认为这比实际上要简单得多。其他人可能也会考虑拆分字符串。
【解决方案2】:

这是一种结合使用 STUFF 和 PATINDEX 的方法。

它只会替换评论中第一次出现的名称。
所以它可能必须执行多次,直到它没有更新任何内容。

UPDATE c
SET c.Comment = STUFF(c.Comment, PATINDEX('%[^a-z0-9]'+en.FirstName+'[^a-z0-9]%', '/'+c.Comment+'/'), len(en.FirstName), 'employee')
FROM AnswerComment c
JOIN #EmployeeNames en ON en.SurveyId = c.SurveyId
WHERE '/'+c.Comment+'/' LIKE '%[^a-z0-9]'+en.FirstName+'[^a-z0-9]%';

【讨论】:

    猜你喜欢
    • 2019-06-07
    • 1970-01-01
    • 2011-08-31
    • 1970-01-01
    • 2011-06-18
    • 2021-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多