【发布时间】:2012-12-13 10:48:22
【问题描述】:
我在用 SQL 开发匹配算法时遇到问题。我有一张桌子subjects。这些中的每一个都需要与表controls 中相同数量的行匹配(为了这个问题,假设需要为每个主题选择两行或控件)。所选控件的位置必须完全匹配,并且所选控件的match_field 中的值应尽可能接近主题。
这是一些示例数据:
表格主题:
id location match_field
1 1 190
2 2 2000
3 1 100
表格控件:
id location match_field
17 1 70
11 1 180
12 1 220
13 1 240
14 1 500
15 1 600
16 1 600
10 2 30
78 2 1840
79 2 2250
这将是样本数据的最佳结果:
subject_id control_id location match_field_diff
1 12 1 30
1 13 1 50
2 78 2 160
2 79 2 250
3 17 1 30
3 11 1 80
这很棘手,因为例如,控件 11 是与主题 1 最接近的匹配项。但是,在最佳解决方案中,控件 11 与主题 3 匹配。
我相信Hungarian Algorithm 接近这个问题的“正确”解决方案。但是,受试者和对照的数量并不相同,也不会使用所有对照(我有几千名受试者和几百万个潜在对照)。
没有必要获得绝对最优的结果;一个很好的近似值对我来说很好。
似乎应该有一个很好的基于集合的解决方案来解决这个问题,但我想不出该怎么做。下面是一些仅根据位置为每个主题分配相同数量的控件的代码:
select * from (
select subject.id,
control.id,
subject.location,
row_number() over (
partition by subject.location
order by subject.id, control.id
) as rn,
count(distinct control.id) over (
partition by subject.location
) as controls_in_loc
from subjects
join controls on control.location = subject.location
)
where mod(rn,controls_in_loc+1) = 1
但是,我不知道如何添加模糊匹配组件。我正在使用 DB2,但如果您使用其他算法,可以将算法转换为 DB2。
提前感谢您的帮助!
更新:我主要相信 SQL 不是这项工作的正确工具。然而,为了确定(并且因为这是一个有趣的问题),我提供了一个赏金来看看是否有可能工作的 SQL 解决方案。它需要是一个基于集合的解决方案。它可以使用迭代(在同一个查询上多次循环以获得结果),但迭代次数需要远小于大表的行数。它不应遍历表中的每个元素或使用游标。
【问题讨论】:
-
在最优解中,为什么要将对照 11 (180) 匹配到主题 2 (2000) 而不是主题 1 (190)?
-
@Pharaoh,哎呀,这是一个错字。已更正,谢谢。
-
@dan1111 。 . .如果有一个简单的基于集合的解决方案,我会感到惊讶。 SQL 是相当确定性的。很难想象如何将其中一个控件分配给不是最接近的主题的主题。不过,有趣的问题。你能简要描述一下这个应用在现实世界中的问题吗?
-
@GordonLinoff,用于科学研究,从数据库中创建匹配的对照组。
-
我承诺你没有办法在使用有限数量的子查询的单个
SELECT查询中做到这一点!最简单的可能方法是在二分图中寻找未加权的最大匹配,只要它们的match_fields 差异小于某个固定阈值,就在主题和控件之间放置一条边,并解决即使你需要 迭代.
标签: sql algorithm db2 combinatorics