【问题标题】:query sqlite to LIKE but whole words将 sqlite 查询为 LIKE 但整个单词
【发布时间】:2013-05-09 06:20:48
【问题描述】:

我有两张桌子: 表A:id,字符串A 表B:id,字符串B

从 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+'"

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

【问题讨论】:

标签: python sql sqlite


【解决方案1】:

像这样构建一个 where 子句:

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

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

【讨论】:

    【解决方案2】:

    你可以定义一个 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 的方法可能更快。

    【讨论】:

    • 其实很整洁。这是一个我正在考虑偶尔运行的脚本,并且正则表达式会给我更多的调整能力。感谢您的宝贵时间
    【解决方案3】:

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

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

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

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

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

    除此之外,它们是相同的。其实GLOB和LIKE都是实现的 使用相同的子程序,使用不同的参数调用,这些参数决定了 通配符和区分大小写。

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

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

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

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

    【讨论】:

      【解决方案4】:

      你可以这样做;

      WHERE StringB LIKE "%'+stringa+'%"
      

      【讨论】:

        猜你喜欢
        • 2014-09-17
        • 1970-01-01
        • 2018-07-23
        • 2011-05-11
        • 2011-09-11
        • 2015-08-11
        • 2015-02-05
        • 2016-10-07
        • 1970-01-01
        相关资源
        最近更新 更多