2009-04-08 136 views
4

假设您有一个包含varchar列的大表。匹配包含单词排列的行

你会如何匹配包含在VARCHAR山坳的“首选”,但数据是有点吵,包含偶尔拼写错误,例如,字行:

['$2.10 Cumulative Convertible Preffered Stock, $25 par value', 
'5.95% Preferres Stock', 
'Class A Preffered', 
'Series A Peferred Shares', 
'Series A Perferred Shares', 
'Series A Prefered Stock', 
'Series A Preffered Stock', 
'Perfered', 
'Preffered C'] 

字的排列在“优选”上面的拼写错误似乎表现为family resemblance,但它们几乎没有什么共同之处。请注意,拆分每个单词并在每行中的每个单词上运行levenshtein将会非常昂贵。

UPDATE:

有几个这样的,例如,其它实施例与“限制”:

['Resticted Stock Plan', 
'resticted securities', 
'Ristricted Common Stock', 
'Common stock (restrticted, subject to vesting)', 
'Common Stock (Retricted)', 
'Restircted Stock Award', 
'Restriced Common Stock',] 
+0

您是否具体询问“首选”,或者这是一个普遍问题? – 2009-04-08 22:27:09

+0

这里有一小部分其他示例 – 2009-04-08 22:29:38

回答

1

你能试着训练它放在你的桌子的小样本找到潜在的错误拼写(采用分体式+莱文斯坦),然后使用在全表所产生的单词列表?

1

正试图在TSQL或什么语言做到这一点?

您可能能够用正则表达式击中大多数人。

你想知道那不是盖敏感以下

"p(er|re|e)f{1,2}er{1,2}ed" 

"r(e|i)s?t(ri|ir|rti|i)ct?ed" 

的一些变化......

2

创建两个表,拼写和可能speelings的:

- - 你可以找出类型

create table spelling (id, word) ; 
create table possible_spelling 
(id, spelling_id references spelling(id), spelling) 
-- possible spelling also includes the correct spelling 
-- all values are lowercase 

insert into spelling(word) values ('preferred'); 
insert into possible_spelling(spelling_id, spelling) 
select 1, '%preferred%' union select 1, '%prefered%' union ....; 

select * 
from bigtable a 
join possible_spelling b 
on (lower(a.data) like b.spelling) 
join spelling c on (b.spelling_id = c.id) 
where c.word = 'preferred'; 

异议:thi会很慢,需要设置。 答:不那么慢,这应该是一次性分类和修复你的数据。一次设置,每传入一行进行分类一次。

1

我可能会做这样的事情 - 如果你能与莱文斯坦逃脱一次 - 这里是an amazing spellchecker implementation by Peter Norvig

import re, collections 

def words(text): return re.findall('[a-z]+', text.lower()) 

def train(features): 
    model = collections.defaultdict(lambda: 1) 
    for f in features: 
     model[f] += 1 
    return model 

NWORDS = train(words(file('big.txt').read())) 

alphabet = 'abcdefghijklmnopqrstuvwxyz' 

def edits1(word): 
    s = [(word[:i], word[i:]) for i in range(len(word) + 1)] 
    deletes = [a + b[1:] for a, b in s if b] 
    transposes = [a + b[1] + b[0] + b[2:] for a, b in s if len(b)>1] 
    replaces = [a + c + b[1:] for a, b in s for c in alphabet if b] 
    inserts = [a + c + b  for a, b in s for c in alphabet] 
    return set(deletes + transposes + replaces + inserts) 

def known_edits2(word): 
    return set(e2 for e1 in edits1(word) for e2 in edits1(e1) if e2 in NWORDS) 

def known(words): return set(w for w in words if w in NWORDS) 

def correct(word): 
    candidates = known([word]) or known(edits1(word)) or known_edits2(word) or [word] 
    return max(candidates, key=NWORDS.get) 

他做了个训练组可用here: http://norvig.com/big.txt下面是示例输出:

>>> correct('prefferred') 
'preferred' 
>>> correct('ristricted') 
'restricted' 
>>> correct('ristrickted') 
'restricted' 

对于您的情况,您可以将原始列复制到新列,但是当您这样做时将其传递给拼写检查程序。然后在正确拼写的列上放置一个fulltext索引,并将其与您的查询进行匹配,但返回原始列的结果。你只需要做一次,而不是每次计算距离。您也可以对输入进行拼写检查,或者仅将更正后的版本作为后备检查。无论哪种方式,都值得研究Norvig的例子。