gpt4 book ai didi

postgresql - 如何使用 pg_trgm 按相似值分组

转载 作者:行者123 更新时间:2023-11-29 13:17:17 25 4
gpt4 key购买 nike

我有下表

id error
- ----------------------------------------
1 Error 1234eee5, can not write to disk
2 Error 83457qwe, can not write to disk
3 Error 72344ee, can not write to disk
4 Fatal barier breach on object 72fgsff
5 Fatal barier breach on object 7fasdfa
6 Fatal barier breach on object 73456xcc5

我希望能够得到一个按相似度计算的结果,其中 > 80% 的相似度意味着两个错误相等。我一直在使用 pg_trgm 扩展,它的相似度函数对我来说非常有用,这是我唯一能弄清楚如何生成下面的分组结果的方法。

Error                                  Count
------------------------------------- ------
Error 1234eee5, can not write to disk, 3
Fatal barier breach on object 72fgsff, 3

最佳答案

基本上,您可以将一个表与自身连接起来以查找相似的字符串,但是这种方法将导致对更大数据集的查询非常缓慢。另外,使用similarity()在某些情况下可能会导致不准确(需要找到合适的极限值)。

您应该尝试寻找模式。例如,如果字符串中的所有可变词都以数字开头,您可以使用 regexp_replace():

屏蔽它们
select id, regexp_replace(error, '\d\w+', 'xxxxx') as error
from errors;

id | error
----+-------------------------------------
1 | Error xxxxx, can not write to disk
2 | Error xxxxx, can not write to disk
3 | Error xxxxx, can not write to disk
4 | Fatal barier breach on object xxxxx
5 | Fatal barier breach on object xxxxx
6 | Fatal barier breach on object xxxxx
(6 rows)

因此您可以轻松地按错误消息对数据进行分组:

select regexp_replace(error, '\d\w+', 'xxxxx') as error, count(*)
from errors
group by 1;

error | count
-------------------------------------+-------
Error xxxxx, can not write to disk | 3
Fatal barier breach on object xxxxx | 3
(2 rows)

上述查询只是一个示例,具体的解决方案取决于数据格式。

使用 pg_trgm

基于 OP 想法的解决方案(请参阅下面的评论)。 similarity() 的限制 0.8 肯定太高了。看起来应该在 0.6 左右。

unique 错误表(我使用了一个临时表,但它当然也是一个常规表):

create temp table if not exists unique_errors(
id serial primary key,
error text,
ids int[]);

ids 列用于存储基表中包含类似错误的行的id

do $$
declare
e record;
found_id int;
begin
truncate unique_errors;
for e in select * from errors loop
select min(id)
into found_id
from unique_errors u
where similarity(u.error, e.error) > 0.6;
if found_id is not null then
update unique_errors
set ids = ids || e.id
where id = found_id;
else
insert into unique_errors (error, ids)
values (e.error, array[e.id]);
end if;
end loop;
end $$;

最终结果:

select *, cardinality(ids) as count
from unique_errors;

id | error | ids | count
----+---------------------------------------+---------+-------
1 | Error 1234eee5, can not write to disk | {1,2,3} | 3
2 | Fatal barier breach on object 72fgsff | {4,5,6} | 3
(2 rows)

关于postgresql - 如何使用 pg_trgm 按相似值分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47212230/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com