Ste*_*ose 6 sql sql-server replace where-clause
我有一张桌子:
| id | lastname | firstname |
| 1 | doe | john |
| 2 | oman | donald |
| 3 | o'neill | james |
| 4 | onackers | sharon |
Run Code Online (Sandbox Code Playgroud)
基本上,用户将使用姓氏的第一个字母进行搜索.
我希望能够从数据库返回包含和不包含标点符号的结果.例如,当用户搜索:on时
我想两个回复: o'neill,onackers
我希望有人能够搜索"o,on,oneill,oill等"来获取o'neill.
因此,执行此操作的最佳方法似乎是使用lastname列值,并在WHERE子句中使用OR搜索它的两个排列.在SQL中用_替换任何特殊字符的地方,以及所有非alpha字符(包括空格)都消失的字符.
我想我可以在SQL替换中使用下划线来保持一个空间可用.
我在使用WHERE子句时遇到了一些麻烦.我宁愿用一个简单的REPLACE来做这个,而不是在可能的情况下创建一个正则表达式函数.如果那是不合适的,我理解:
@last_name (this is the nvarchar input)
SELECT id, lastname, firstname
FROM people
WHERE ((REPLACE(people.lastname, '[^A-Za-z]', '_') like @last_name + '%')
OR (REPLACE(people.lastnname,'[^A-Za-z ]', '') like @last_name + '%'))
ORDER BY lastname
Run Code Online (Sandbox Code Playgroud)
我很确定更换部件必须位于LIKE的另一侧.我弄乱了结构,但需要一些帮助.
我正在使用MSSQL Server 2005.
非常感谢你提前.
UPDATE
看来我有两个选择:
数据库每晚更新一次.我实际上已经开始采用新的表格方法,因为这是我原本打算做的.但是,我开始认为将"模糊"列添加到主表然后每晚更新以将调整后的姓名添加到新的/更新的行更聪明.
Stack Overflow:哪种方法更好?我可以在SQL中使用用户定义的REGEX函数,从而避免额外的列?或者将额外的一列或两列添加到表中?还是一张新桌子?
根据您的场景的复杂程度,这将是大量工作,而且速度也很慢。但还有更灵活的方法。考虑这样的事情,称为initialTable:
| id | lastname | firstname |\n| 1 | o\'malley | jos\xc3\xa9 |\n| 2 | om\xc3\xa1ll\xc3\xa8y | d\xc3\xb2n\xc3\xa1ld |\n| 3 | o\'neill | j\xc3\xa1m\xc3\xa8s |\n| 4 | onackers | sharon |\nRun Code Online (Sandbox Code Playgroud)\n\n也许有点多,但它说明了普遍问题。我必须根据看起来非常相似的字符数据对我们的内联网网站实施“模糊”搜索 - 例如,法语或西班牙语名称或街道地址中有很多重音。
\n\n我所做的是定义一个函数,该函数执行给定字符串的所有替换,例如(伪代码):
\n\nfunction string replacestuff(string input)\n{\n input = replace(input, "\xc3\xa8", "e");\n input = replace(input, "\xc3\xa9", "e");\n input = replace(input, "\xc3\xb2", "o");\n input = replace(input, "\xc3\xb3", "o");\n input = replace(input, "\'", "");\n ...\n return input;\n}\nRun Code Online (Sandbox Code Playgroud)\n\n使用此转换函数创建fuzzyTable具有以下内容的第二个表:
| id | lastname | firstname |\n| 1 | omalley | jose |\n| 2 | omalley | donald |\n| 3 | oneill | james |\n| 4 | onackers | sharon |\nRun Code Online (Sandbox Code Playgroud)\n\n现在,假设您将获得一个用于搜索 的输入字符串jos\xc3\xa8。这在两个表中都找不到。你需要做的是:
declare @input varchar(50)\ndeclare @input_mod varchar(50)\nset @input = \'jos\xc3\xa8\'\nset @input_mod = replacestuff(@input)\n\nSELECT id FROM initialTable WHERE firstname like @input OR firstname like @input_mod\nUNION\nSELECT id FROM fuzzyTable WHERE firstname like @input OR firstname like @input_mod\nGROUP BY id\nRun Code Online (Sandbox Code Playgroud)\n\n(当然,您必须添加%才能LIKE工作。)这里的关键是使用替换功能修改您输入的搜索字符串;s\xc3\xa8这样,如果搜索的内容,您将获得匹配项,s\xc3\xa9因为两者都取决于se替换函数处理的时间。
您甚至可以进行两级搜索;首先根据正确的表仅检查未修改的字符串,然后如果用户这么说,则使用上面显示的语句进行模糊搜索。
\n\n这是一种非常灵活的方法,可以处理各种内容,例如使用两个字母表达式 ae、oe、ue、ss 查找德语字母 \xc3\xa4、\xc3\xb6、\xc3\xbc、\xc3\x9f 。缺点是您必须保留某些数据的重复项,并随着初始表(或替换函数)的更改而更改 fuzzyTable 中的这些重复项。在我们当前的用例中,内联网数据库每晚更新一次,因此这不是问题。
\n\n编辑
\n\n您需要注意,使用此功能在某些情况下您会得到误报。例如,我们将其用于员工搜索,如果您将荷兰语姓名拼写为Hoek,那么您也会在搜索 时找到此姓名H\xc3\xb6k,因为在德语中, 的替代品\xc3\xb6将是oe。这可以使用国家/地区感知替换功能来解决,但我们从未将这个概念发展到这一步。根据您的输入数据,这或多或少是学术性的,对于我们的用例,我不记得有人抱怨过。
我们首先提出这种方法的主要原因是我们必须处理的一些数据充满了拼写错误,即。在法语中,许多元音的重音都是错误的,但我们仍然需要提供一个结果。
\n| 归档时间: |
|
| 查看次数: |
28526 次 |
| 最近记录: |