我从两个不同的来源获得了记录,目标是在彼此匹配的来源之间创建链接。为此,应用了经过训练的 AI 模型,该模型将每条记录从源 A 分配给源 B 的每个记录的匹配概率分数。然后,表score
如下所示。
src_a_id src_b_id score
-----------------------------
1 foo 0.8
1 bar 0.7
1 baz 0.6
2 foo 0.9
2 bar 0.5
2 baz 0.3
现在我需要从此表中读取与 id1
src_a
记录最有可能的计数器匹配。当您使用 sqlSELECT * FROM score WHERE src_a_id = 1 ORDER BY score DESC;
选择数据时,您将获得此结果。
src_a_id src_b_id score
-----------------------------
1 foo 0.8
1 bar 0.7
1 baz 0.6
在这里,看起来第一行是我正在寻找的结果,因此计数器匹配是src_b
记录,带有 idfoo
具有相互得分0.8
但不正确。我们可以从另一端查询以验证结果。什么是 idfoo
src_b
的计数器匹配?使用 sqlSELECT * FROM score WHERE src_b_id = 'foo' ORDER BY score DESC;
我们得到结果:
src_a_id src_b_id score
-----------------------------
2 foo 0.9
1 foo 0.8
从第一个查询开始,它看起来像src_a
id1
与 idfoo
src_b
匹配。 从第二个查询中可以清楚地看出,之前的结论是错误的src_b
因为 idfoo
与src_a
id2
匹配,因为这对具有更高的互分。
考虑到该表将有数千条记录,我应该如何编写查询以查找与具有 id1
src_a
记录的匹配项?
我的第一步是在 Postgres 中搜索一些递归查询,但我发现的教程不适合我的用例,老实说,到目前为止,我完全无法组成任何工作应用程序。
编辑
对于创建测试数据的演示语法:
CREATE TABLE score (
src_a_id integer NOT NULL,
src_b_id varchar(255) NOT NULL,
score decimal(3,2) NOT NULL
);
INSERT INTO score (src_a_id, src_b_id, score)
VALUES
(1, 'foo', 0.8),
(1, 'bar', 0.7),
(1, 'baz', 0.6),
(2, 'foo', 0.9),
(2, 'bar', 0.5),
(2, 'baz', 0.3);
从测试数据可以得出存在两对。
1
匹配bar
2
比赛foo
baz
没有匹配项
如何查询src_a ID1
匹配?预期结果是 src_b idbar
。从另一边。如何查询src_b IDbar
匹配项?预期结果是 src_a id1
。
似乎可以通过使用窗口函数row_number() over(<partition>)
来解决您的问题。你想要的是找到这样的对,其中每个ID的分数是最大的。
给定您提供的示例数据集 - 我们可以编写此 CTE,其中我们有 2 个行号(每个 id 一个),然后将它们相加以得到一对的排名:
with ranks as (
select
src_a_id,
src_b_id, score,
row_number() over (partition by src_b_id order by score desc) src_b_idx,
row_number() over (partition by src_a_id order by score desc)
+ row_number() over (partition by src_b_id order by score desc) pair_rank
from score
)
这样,你会得到这个结果:
src_a_id src_b_id score pair_rank
-------------------------------------
1 bar 0.7 3
1 baz 0.6 5
1 foo 0.8 3
2 bar 0.5 5
2 baz 0.8 3
2 foo 0.9 2
现在,您可以选择pair_rank
最小的对
select src_a_id, src_b_id, score from (
select src_a_id, src_b_id, score,
row_number() over (partition by src_a_id order by pair_rank, src_b_idx) as index
from ranks
) data where index = 1 and <CONDITION> (e.g. src_a_id = <YOUR ID>)
如果否,查询将产生分数最高的所有对
src_a_id src_b_id score
-------------------------
1 bar 0.7
2 foo 0.9
>编辑: 在几种边缘情况下,上述方法会产生模棱两可/不正确的结果:
- 给定
src_A_id
的所有对的分数低于共享相同src_B_id
的任何其他对(查询是否应返回 null/0 行/所有src_A_id
中最高? - 具有相同最高分的多对共享
src_B_id
(鉴于src_A_id不同,哪一个胜过另一个? - 多个不同的
src_A_id
为同一提供最高分src_B_id
(同样,鉴于src_A_id和src_B_id相同,哪一个胜过另一个?
给定以下数据集,您可以观察所有 3 种情况:
src_a_id src_b_id score
------------------------
1 foo 0.8 |
1 bar 0.7 | -> all pairs are beanten by some other src_a_id
1 baz 0.6 |
2 foo 0.9
2 bar 0.5
2 baz 0.8 -> higest for `baz`, but 3.baz has the same score
3 foo 0.91 |
3 bar 0.91 | -> both pairs are the higest, but share src_a_id
3 baz 0.8
这是改编的脚本,但您可以根据所需的行为进行调整:
b_rank as (
select
src_a_id, src_b_id,
rank() over (partition by src_b_id order by score desc) src_b_idx
from score
)
select src_a_id, src_b_id, score from (
select
rank() over (partition by s.src_a_id order by score desc) score_rank, s.*
from score s
join b_rank b on s.src_a_id = b.src_a_id and s.src_b_id = b.src_b_id and src_b_idx = 1
) data where score_rank = 1 and src_a_id = XXX
其中产生:
null
是否取所有对(示例src_a_id
= 1)- 得分最高的对,即使相同的分数由另一个
src_b_id
共享(示例src_a_id
= 2) - 如果所有这些对在给定相同
src_a_id
的情况下得分最高,则多行(示例src_a_id
= 3)