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

nkkqxpd9  于 2023-08-04  发布在  PostgreSQL
关注(0)|答案(3)|浏览(121)

我有一个表,其中一列有记录,只是它们的书写方式不同。那么,我如何找到它们并将相应的id保存在新表中呢?
我在城市一栏中有以下记录。

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

字符串
所以我的第一个假设是删除任何特殊字符,包括白色,然后小写。看看谁匹配,然后将id写入新表?
什么是最好的和最可靠的方法来找到machtes?

xriantvc

xriantvc1#

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

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根据查询结果创建新表。
相关信息:

bhmjp9jg

bhmjp9jg2#

这当然可以优化,但它的工作原理:

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;

字符串

t3psigkw

t3psigkw3#

在我看来,你是在尝试低edit distance。当我在处理低质量的手动输入的数据时遇到类似的问题时,我使用了一个“正确”的地名列表(在示例数据中可能是“纽约”),然后使用所有错误数据行和所有正确名称的交叉连接,计算每个配对的编辑距离,并将每个配对的最小值作为“匹配”。
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

字符串

相关问题