首页 > 解决方案 > 高效的字符串匹配与 SQL 和 Python

问题描述

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

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

我觉得我效率低下。在“伪代码”中,拥有 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 进行字符串匹配的指导都将受到高度赞赏。谢谢你。

标签: pythonpsycopg2psqlstring-matching

解决方案


两个 SELECT 查询都在同一个pub_tables表上。并且对 zip-match 的第二个查询的内部循环对pub_tables. 您可以通过对其自身进行 INNER JOIN 直接在一个查询中获得 zip 相等比较pub_tables

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)循环内的参数化。否则,您只是一遍又一遍地重新定义相同的静态字符串。


推荐阅读