检查 table 相似的文本记录并删除重复记录(SQL Oracle 数据库。)
Check table for similar text records and remove duplicate records (SQL Oracle database. )
我需要检查 oracle 数据库 table 是否有相似的记录并获取不同的字符数。为此,我使用此查询:
CREATE TABLE match_tab (
id NUMBER,
col1 VARCHAR2(15),
CONSTRAINT match_tab_pk PRIMARY KEY (id)
);
INSERT INTO match_tab VALUES (1, 'Peter Parker');
INSERT INTO match_tab VALUES (2, 'peter parker');
INSERT INTO match_tab VALUES (3, 'Clark Kent' );
INSERT INTO match_tab VALUES (4, 'Wonder Woman');
INSERT INTO match_tab VALUES (5, 'Superman');
INSERT INTO match_tab VALUES (6, 'The Hulk');
INSERT INTO match_tab VALUES (7, 'Ponder Woman');
INSERT INTO match_tab VALUES (8, 'Claire Kent' );
INSERT INTO match_tab VALUES (9, 'Superman');
INSERT INTO match_tab VALUES (10, 'Iron Man');
COMMIT;
select m1.col1 as mc1,
m2.col1 as mc2,
UTL_MATCH.edit_distance(m1.col1, m2.col1) as match
from match_tab m1
join match_tab m2 on (1 = 1)
where UTL_MATCH.edit_distance(m1.col1, m2.col1) = 2 and m1.id != m2.id;
给出结果:
MC1 MC2 MATCH
--------------- --------------- ----------
Peter Parker peter parker 2
peter parker Peter Parker 2
Clark Kent Claire Kent 2
Claire Kent Clark Kent 2
如何删除重复的记录并得到这样的结果:
MC1 MC2 MATCH
--------------- --------------- ----------
Peter Parker peter parker 2
Clark Kent Claire Kent 2
是否可以优化此查询?对于大量数据,
需要很长时间。
我将不胜感激任何帮助!
删除“重复项”很简单(例如使用 <
而不是 !=
):
SQL> SELECT m1.col1 AS mc1,
2 m2.col1 AS mc2,
3 UTL_MATCH.edit_distance (m1.col1, m2.col1) AS match
4 FROM match_tab m1
5 JOIN match_tab m2
6 ON UTL_MATCH.edit_distance (m1.col1, m2.col1) = 2
7 AND m1.id < m2.id;
MC1 MC2 MATCH
--------------- --------------- ----------
Peter Parker peter parker 2
Clark Kent Claire Kent 2
SQL>
如何让它更快?我不知道你是否可以让它更快;您正在比较所有行,并且 - 对于大表 - 这需要时间。
我删除了你的 cross-join(使用 on 1 = 1
),因为你实际上可以在 utl_match.edit_distance
上加入 m1
和 m2
,但我不希望这是对您的代码的重大改进。
您可以:
- 使用分层查询,这样您就不需要阅读 table 两次,也不需要 self-join;
- 添加过滤器以检查列的长度是否相似(这可能比使用
UTL_MATCH
更简单,如果优化器首先使用此过滤器,它可能能够排除很多比较) ;和
- 过滤
PRIOR id < id
而不是使用 !=
来比较 id
并消除重复项:
SELECT PRIOR col1 as mc1,
col1 as mc2,
UTL_MATCH.edit_distance(PRIOR col1, col1) as match
FROM match_tab
WHERE LEVEL = 2
CONNECT BY
LENGTH(PRIOR col1) - LENGTH(col1) BETWEEN -1 AND +1
AND PRIOR id < id
AND UTL_MATCH.edit_distance(PRIOR col1, col1) BETWEEN 1 AND 2;
对于您的示例数据,输出:
MC1
MC2
MATCH
Peter Parker
peter parker
2
Clark Kent
Claire Kent
2
Wonder Woman
Ponder Woman
1
注意:如果您只想要 edit-distance 为 2
的匹配项,则将最后一行更改为 AND UTL_MATCH.edit_distance(PRIOR col1, col1) = 2;
db<>fiddle here
我需要检查 oracle 数据库 table 是否有相似的记录并获取不同的字符数。为此,我使用此查询:
CREATE TABLE match_tab (
id NUMBER,
col1 VARCHAR2(15),
CONSTRAINT match_tab_pk PRIMARY KEY (id)
);
INSERT INTO match_tab VALUES (1, 'Peter Parker');
INSERT INTO match_tab VALUES (2, 'peter parker');
INSERT INTO match_tab VALUES (3, 'Clark Kent' );
INSERT INTO match_tab VALUES (4, 'Wonder Woman');
INSERT INTO match_tab VALUES (5, 'Superman');
INSERT INTO match_tab VALUES (6, 'The Hulk');
INSERT INTO match_tab VALUES (7, 'Ponder Woman');
INSERT INTO match_tab VALUES (8, 'Claire Kent' );
INSERT INTO match_tab VALUES (9, 'Superman');
INSERT INTO match_tab VALUES (10, 'Iron Man');
COMMIT;
select m1.col1 as mc1,
m2.col1 as mc2,
UTL_MATCH.edit_distance(m1.col1, m2.col1) as match
from match_tab m1
join match_tab m2 on (1 = 1)
where UTL_MATCH.edit_distance(m1.col1, m2.col1) = 2 and m1.id != m2.id;
给出结果:
MC1 MC2 MATCH
--------------- --------------- ----------
Peter Parker peter parker 2
peter parker Peter Parker 2
Clark Kent Claire Kent 2
Claire Kent Clark Kent 2
如何删除重复的记录并得到这样的结果:
MC1 MC2 MATCH --------------- --------------- ---------- Peter Parker peter parker 2 Clark Kent Claire Kent 2
是否可以优化此查询?对于大量数据, 需要很长时间。
我将不胜感激任何帮助!
删除“重复项”很简单(例如使用 <
而不是 !=
):
SQL> SELECT m1.col1 AS mc1,
2 m2.col1 AS mc2,
3 UTL_MATCH.edit_distance (m1.col1, m2.col1) AS match
4 FROM match_tab m1
5 JOIN match_tab m2
6 ON UTL_MATCH.edit_distance (m1.col1, m2.col1) = 2
7 AND m1.id < m2.id;
MC1 MC2 MATCH
--------------- --------------- ----------
Peter Parker peter parker 2
Clark Kent Claire Kent 2
SQL>
如何让它更快?我不知道你是否可以让它更快;您正在比较所有行,并且 - 对于大表 - 这需要时间。
我删除了你的 cross-join(使用 on 1 = 1
),因为你实际上可以在 utl_match.edit_distance
上加入 m1
和 m2
,但我不希望这是对您的代码的重大改进。
您可以:
- 使用分层查询,这样您就不需要阅读 table 两次,也不需要 self-join;
- 添加过滤器以检查列的长度是否相似(这可能比使用
UTL_MATCH
更简单,如果优化器首先使用此过滤器,它可能能够排除很多比较) ;和 - 过滤
PRIOR id < id
而不是使用!=
来比较id
并消除重复项:
SELECT PRIOR col1 as mc1,
col1 as mc2,
UTL_MATCH.edit_distance(PRIOR col1, col1) as match
FROM match_tab
WHERE LEVEL = 2
CONNECT BY
LENGTH(PRIOR col1) - LENGTH(col1) BETWEEN -1 AND +1
AND PRIOR id < id
AND UTL_MATCH.edit_distance(PRIOR col1, col1) BETWEEN 1 AND 2;
对于您的示例数据,输出:
MC1 MC2 MATCH Peter Parker peter parker 2 Clark Kent Claire Kent 2 Wonder Woman Ponder Woman 1
注意:如果您只想要 edit-distance 为 2
的匹配项,则将最后一行更改为 AND UTL_MATCH.edit_distance(PRIOR col1, col1) = 2;
db<>fiddle here