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)
保留在循环内。否则,您只是一遍又一遍地重新定义同一个静态字符串。
我想知道使用 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)
保留在循环内。否则,您只是一遍又一遍地重新定义同一个静态字符串。