我有一个表,其中一列包含记录,只是它们的写入方式有所不同。 那么我怎样才能找到这些并将相应的 id 保存在新表中呢?
例如我在城市列中有以下记录。
Id name
1 berlin
2 ber lin
3 ber-lin
4 Berlin
5 Hamburg
6 New York
7 NewYork
所以我的第一个假设是删除所有特殊字符,包括空格,然后是小写字母。然后看看谁匹配然后将id写入新表?
寻找大砍刀的最佳且最可靠的方法是什么?
如果删除一些字符(示例中的“ ”和“-”)和小写字母足以识别重复项:
CREATE TABLE tbl_folded AS
SELECT lower(translate(name, ' -', '')) AS base_name
, array_agg(id) AS ids
FROM tbl
GROUP BY 1;
translate()
对于替换(或删除)单个字符列表特别有用。CREATE TABLE AS
根据查询结果创建新表。
相关:
这当然可以优化,但它确实有效:
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;
在我看来,您正在尝试较低的编辑距离。当我遇到类似的低质量手动输入数据问题时,我使用了“正确”地名列表(示例数据中可能是“纽约”),然后使用所有不良数据行的交叉联接以及所有正确的名称,计算每个配对的编辑距离,并将每个配对的最小值作为“匹配”。
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