2

我有两个表: TableA: id, StringA TableB: id, StringB

从 TableA 中获取所有行后,我想匹配尽可能接近 TableB 中的单词。我正在尝试做这样的事情:

c.execute('SELECT id, StringB FROM TableB WHERE StringB LIKE "'+stringa+'%" COLLATE NOCASE')
foundrows=c.fetchall()
if (len(foundrows)>0):
    print 'Hmm. Which one...'
    for foundrow in foundrows:    
        print 'looking for:'+stringa+'  found:'+ foundrow[1]

这给了我类似的东西:

Hmm. Which one...
looking for:goo  found:good
looking for:goo  found:good 1
looking for:goo  found:good 2
looking for:goo  found:good 1 dk
looking for:goo  found:good 2 dk
looking for:goo  found:Good Friday
looking for:goo  found:goose
looking for:goo  found:Good Friday 1
looking for:goo  found:good sport
looking for:goo  found:good job
looking for:goo  found:good morning
looking for:goo  found:good night
looking for:goo  found:goodbye 1
looking for:goo  found:goodbye e
looking for:goo  found:goodbye

我真正想做的是'SELECT id, StringB FROM TableB WHERE StringB CONTAINS WORD "'+stringa+'"

实现“包含单词”的最佳方法是什么?

4

4 回答 4

10

像这样构建一个 where 子句:

where (' ' || StringB || ' ') LIKE '% stringa %'

周围的空格StringB确保您在字符串的开头和结尾捕捉到单词。

于 2013-05-08T21:37:53.277 回答
3

您可以定义一个 REGEXP 函数:

import sqlite3
import re
def regexp(expr, item):
    reg = re.compile(expr)
    return reg.search(item) is not None

conn = sqlite3.connect(':memory:')
conn.create_function("REGEXP", 2, regexp)
cursor = conn.cursor()
cursor.execute('CREATE TABLE foo (bar TEXT)')
cursor.executemany(
    'INSERT INTO foo (bar) VALUES (?)', [
        ('this is not good', ),
        ('world of goo', ),
        ('goo: the final frontier', ),
        ('goo',)])
cursor.execute('SELECT bar FROM foo WHERE bar REGEXP ?', [r'\bgoo\b'])
# cursor.execute('SELECT bar FROM foo WHERE (" " || bar || " ") LIKE ?', ["% goo %"])
data = cursor.fetchall()
print(data)

产量

[(u'world of goo',), (u'goo: the final frontier',), (u'goo',)]

另请注意,正则表达式\bgoo\b将匹配不是空格的单词边界。例如,如果您有一个表值goo:\bgoo\b则将匹配它,但" " || bar || " " LIKE "% goo %"不会。


在进行 sqlite 查询时拥有正则表达式的功能可能会很好,但它可能不是很快,因为它需要对表中的每个项目调用 Python 函数。

假设您要搜索的单词没有被标点符号或空格以外的其他单词边界包围,Blorgbeard 的方法可能更快。

于 2013-05-08T21:53:52.970 回答
1

您可以使用glob函数(或运算符)进行区分大小写的比较。来自 SQLite 用户邮件列表上的 D. Richard Hipp:

LIKE 不区分大小写并使用通配符 '%' 和 '_'

GLOB 区分大小写并使用通配符“*”和“?”。

GLOB 还允许您说“[abcd]”来表示“abcd”集中的任何字符。

LIKE 可以有一个用于转义通配符的选项 ESCAPE 字符。GLOB 不能。但是对于 GLOB,如果您想匹配通配符,您可以使用 '[*]' 或 '[?]'。

除此之外,它们是相同的。事实上,GLOB 和 LIKE 是使用相同的子例程实现的,调用时使用不同的参数来确定通配符和区分大小写。

如果您真的想匹配整个单词,您将需要多个测试的 OR。例如,

WHERE glob(StringB + ' *',        StringA)
   OR glob('* ' + StringB,        StringA)
   OR glob('* ' + StringB + ' *', StringA)

分别在 StringA 的开头、结尾和中间捕获单词。或者基于 Blorgbeard 的回应

WHERE glob(' '+StringB+' ','* '+StringA+' *')
于 2013-05-08T21:44:32.110 回答
0

你可以这样做;

WHERE StringB LIKE "%'+stringa+'%"
于 2013-05-08T21:36:06.660 回答