SQL 和 Python 的高效字符串匹配

Efficient string Match with SQL and Python

我想知道使用 Python 和 PSQL 数据库进行字符串匹配的最佳方法是什么。我的数据库包含酒吧名称和邮政编码。我想检查是否有评论指的是同一家酒吧但拼写错误。

从概念上讲,我正在考虑遍历所有名称,并针对同一邮政编码中的每一行,使用 strsim 获取字符串相似性度量。如果此指标高于阈值,我将其插入到另一个存储匹配候选者的 SQL table 中。

我觉得我效率低下。在 "pseudo-code" 中,有 pub_table、candidates_table 并使用 JaroWinkler 函数,我的意思是做类似的事情:

from similarity.jarowinkler import JaroWinkler
jarowinkler = JaroWinkler()

cursor = conn.cursor()
cur.execute("SELECT name, zip from pub_table")
rows = cur.fetchall()
for r in rows:
    cur.execute("SELECT name FROM pub_tables WHERE zip = %s", (r[1],))
    search = cur.fetchall()

    for pub in search:
        if jarowinkler.similarity(r[0], pub[0]) > threshold:
             insertion = ("INSERT INTO candidates_table (name1, name2, zip) 
                          VALUES (%s, %s, %s)")
             cur.execute(insertion, (r[0], pub[0], zip))

cursor.close ()
conn.commit ()
conn.close ()

不好意思说不清楚(新手)。任何使用 PSQL 和 Python 进行字符串匹配的指导都将受到高度赞赏。谢谢你。

两个 SELECT 查询都在同一个 pub_tables table 上。并且对 pub_tables 的每一行重复 zip-match 的第二个查询的内循环。您可以通过将 pub_tables 与自身进行 INNER JOIN 来直接在一个查询中获得 zip 相等性比较。

SELECT p1.name, p2.name, p1.zip
FROM   pub_table p1,
       pub_table p2
WHERE  p1.zip = p2.zip
AND    p1.name != p2.name  -- this line assumes your original pub_table
                           -- has unique names for each "same pub in same zip"
                           -- and prevents the entries from matching with themselves.

这会将您的代码减少到仅外部查询和内部检查 + 插入,而无需第二个查询:

cur.execute("<my query as above>")
rows = cur.fetchall()
for r in rows:
    # r[0] and r[1] are the names. r[2] is the zip code
    if jarowinkler.similarity(r[0], r[1]) > threshold:
         insertion = ("INSERT INTO candidates_table (name1, name2, zip) 
                      VALUES (%s, %s, %s)")
         # since r already a tuple with the columns in the right order,
         # you can replace the `(r[0], r[1], r[2])` below with just `r`
         cur.execute(insertion, (r[0], r[1], r[2]))
         # or ...
         cur.execute(insertion, r)

另一个变化:insertion 字符串始终相同,因此您可以将其移动到 for 循环之前,并且只将参数化的 cur.execute(insertion, r) 保留在循环内。否则,您只是一遍又一遍地重新定义同一个静态字符串。