在 SQL (postgres) 中使用哪种搜索策略来查找相似的字符串

问题描述 投票:0回答:3

我有一个表,其中一列包含记录,只是它们的写入方式有所不同。 那么我怎样才能找到这些并将相应的 id 保存在新表中呢?

例如我在城市列中有以下记录。

Id name
1 berlin
2 ber lin
3 ber-lin
4 Berlin
5 Hamburg
6 New York
7 NewYork

所以我的第一个假设是删除所有特殊字符,包括空格,然后是小写字母。然后看看谁匹配然后将id写入新表?

寻找大砍刀的最佳且最可靠的方法是什么?

sql postgresql pattern-matching
3个回答
1
投票

如果删除一些字符(示例中的“ ”和“-”)和小写字母足以识别重复项:

CREATE TABLE tbl_folded AS
SELECT lower(translate(name, ' -', '')) AS base_name
     , array_agg(id) AS ids
FROM   tbl
GROUP  BY 1;

SQL 小提琴

translate()
对于替换(或删除)单个字符列表特别有用。
使用
CREATE TABLE AS
根据查询结果创建新表。

相关:


0
投票

这当然可以优化,但它确实有效:

CREATE TABLE test (id INT(9) NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50) NOT NULL);
INSERT INTO test (id, name) VALUES ('', 'berlin');
INSERT INTO test (id, name) VALUES ('', 'ber lin');
INSERT INTO test (id, name) VALUES ('', 'ber-lin');
INSERT INTO test (id, name) VALUES ('', 'Berlin');
INSERT INTO test (id, name) VALUES ('', 'Hamburg');
INSERT INTO test (id, name) VALUES ('', 'New York');
INSERT INTO test (id, name) VALUES ('', 'NewYork');

CREATE TABLE tmp_clean_text (id INT(9) NOT NULL, name VARCHAR(50) NOT NULL);
INSERT INTO tmp_clean_text (id, name) SELECT id, REPLACE(REPLACE(LOWER(name), ' ', ''), '-', '') FROM test;

CREATE TABLE results (name VARCHAR(50) NOT NULL);

INSERT INTO results (name) SELECT DISTINCT name FROM tmp_clean_text;
UPDATE results SET results.name = CONCAT(results.name, ' ', (
    SELECT GROUP_CONCAT(tmp_clean_text.id)
    FROM tmp_clean_text
    WHERE tmp_clean_text.name = results.name
));

DROP TABLE tmp_clean_text;

0
投票

在我看来,您正在尝试较低的编辑距离。当我遇到类似的低质量手动输入数据问题时,我使用了“正确”地名列表(示例数据中可能是“纽约”),然后使用所有不良数据行的交叉联接以及所有正确的名称,计算每个配对的编辑距离,并将每个配对的最小值作为“匹配”。

PostgreSQL 在其 fuzzystrmatch 库中包含 Levenshtein 编辑距离函数,正如其他人提到的那样。

编辑:这里有一些代码,假设

cities
包含帖子中的数据,并且
normalized_cities
包含
(HAMBURG, BERLIN, NEWYORK)
根据后面的评论:

 select distinct id, name, first_value(normalized_name)
        over (partition by id order by edit_distance)
 from (
 select id, name, normalized_name, 
        levenshtein(upper(name), normalized_name) edit_distance
   from cities cross join normalized_cities
 ) all_pairs

  id |   name   | first_value  
 ----+----------+-------------
   1 | berlin   | BERLIN
   2 | ber lin  | BERLIN
   3 | ber-lin  | BERLIN
   4 | Berlin   | BERLIN
   5 | Hamburg  | HAMBURG
   6 | New York | NEWYORK
   7 | NewYork  | NEWYORK
© www.soinside.com 2019 - 2024. All rights reserved.