考虑一下你是否有两组数字:
组A:
10
20
30
40
另一组更大的数字:
SETB:
15
20
35
40
50
目标是从两组中较大的一组中消除项目,这样两组中的项目数相同,并且您将留下尽可能“接近”的组。我有一个想法,我可以尝试每个项目的所有对,并最小化差异的平方。例如,我认为上述解决方案将是:
SetA SetB Diff DiffSquared
10 15 5 25
20 20 0 0
30 35 5 25
40 40 0 0
DiffSquaredSum == 50
这是解决方案,因为这种组合将为您提供最小的DiffSquaredSum。我并不真正关心项目的配对,主要是将较大的设置修剪为一组相同数量的项目,以及项目尽可能靠近的地方。我意识到我可以使用线性最小二乘的概念来解决这个问题,但我不确定在编码时我会从哪里开始。我更喜欢使用SQL,但我并不关心生成一个精确的解决方案,因为我可以了解一般的方法,因此我可以判断它有多难。
我认为这基本上会涉及尝试两组的所有可能组合:
SetA SetB Diff DiffSquared
10 15 5 25
20 20 0 0
30 35 5 25
40 50 10 100
SetA SetB Diff DiffSquared
10 15 5 25
20 20 0 0
30 40 10 100
40 50 10 100
等。然后选择DiffSquared最小和的组。我可能首先为SetA生成一个row_number,然后为SetB生成一个row_number,然后加入它,这恰好给出了答案,但这只是巧合:
Row# SetA SetB
1 10 15
2 20 20
3 30 35
4 40 40
5 NULL 50
为了确保我找到答案,我需要以某种方式重复这样做,并且有一个ID告诉我哪个组是哪个组合,以便我可以对其进行分组,然后查看每个总和。 我不知道如何获得此设置:
Attempt# Row# SetA SetB
1 1 10 15
1 2 20 20
1 3 30 35
1 4 40 40
2 1 10 15
2 2 20 20
2 3 30 35
2 4 40 50
3 1 10 15
3 2 20 20
3 3 30 40
3 4 40 50
etc....
请注意每次尝试#我已从SetB中删除了其他项目。实际上,SetB可能是许多大于A的项目,因此会消除更多项目,从而有更多可能性。一旦我有了上述内容,我只需添加计算平方差的字段,然后在尝试#上与组进行求和。然后我可以选择具有最小SumDiffSquared的Attempt#。我可能需要将中间结果存储在临时表或表变量中,以便我可以从该ID向后移动以获取成功集中的元素。
所以问题是:如何生成那些“尝试”的所有排列?
答案 0 :(得分:1)
您可以尝试从setB中获取setA中的所有内容(在您的示例中为20和40),然后将setA中的剩余数字相加(10 + 30 = 40)并尝试找到最接近的匹配总和在setB中具有相同数量的操作数(2,10和30)。 在你的例子中,那将是15 + 35 = 50。
我不确定你为何要平衡分歧。
如果您想要两个集合的所有可能组合,则使用不带ON子句的外部联接。
答案 1 :(得分:1)
你没有提到dbms,所以我使用了Oracle。
with crossjoined as(
select b
,a
,abs(a-b) as diff
,row_number() over(partition by b order by abs(a-b), a) as rn
from SetA cross join SetB
)
,ranked as(
select b,a,diff, row_number() over(order by diff,a) as rn
from crossjoined
where rn = 1
)
select b
from ranked
where rn <= (select count(*) from SetA)
order by b;
让我解释它是如何工作的,然后你可以决定我是否正确理解你的问题。该查询包含三个部分:
第1部分“交叉连接” 在这里,我创建了A和B的所有组合。因此,使用您的样本数据,B15与A10,A20,A30,A40等配对。对于每个B,我按差异对所有A进行排名。如果几个A具有相同的差异(如A15和A20对于B15),我首先排序最低的A.这部分查询的示例如下所示。
B A DIFF RN
-- -- ---- --
15 10 5 1
15 20 5 2
15 30 15 3
15 40 25 4
20 20 0 1
20 10 10 2
20 30 10 3
20 40 20 4
第2部分“排名”
查询的这一部分基本上为每个B选择最佳A.这由where rn = 1
实现。每个原始B的结果将有一行。行将按差异排序。如果两行具有相同的差异,则具有最小A的行将首先排序。以下是给出样本数据的“交叉连接”和“排名”的完整结果:
B A DIFF RN
-- -- ---- --
20 20 0 1
40 40 0 2
15 10 5 3
35 30 5 4
50 40 10 5
第3部分“主查询” 现在是时候消除在设置为相同数量的项目的项目作为集A.按照你的逻辑寻找一组具有最小的区别,我使用“排名”部分的排名(rn)并选择前N行。其中N是A中的项目数。
如果我能更详细地解释一下,请告诉我。