当排名函数不够时,排除 select 中的记录
Excluding records in select when rank functions is not enough
我被困在 select 查询中以从 table 中获得最佳匹配,如下所示:
Name
A
B
TotalA
TotalB
Name1
10
1
10
1
Name2
15
2
25
3
Name3
20
3
45
6
Name4
25
4
70
10
Name5
30
5
100
15
Name6
35
6
135
21
Name7
51
7
175
28
.....
....
......
......
......
.....
....
......
......
......
我试图找到 B 总和最低的最佳 6 条记录,但还有一个附加条件,即 A 总和需要高于 150。
这个table按B排序,最好的结果在最前面。因此,6 个最佳结果中 B 的总和为 21,但在这种情况下,A 的总和为 135,低于 150。因此应排除记录 nb 6,并应包括下一个 nb 7。所以最好的结果是记录1-5和记录7中B的总和=22,而A的总和是151,这就足够了。
我使用带分区和顺序的排名函数,但每次查询都返回 0 条记录。是否有可能排除第 6 条记录并将结果取 7,因此 A 的总和将 > 150?
这似乎是 knapsack problem 的一个变体,它是 NP-Complete,最简单的(编码)解决方案就是强制执行每个排列。
鉴于你有固定数量的项目,你可以通过自加入来做到这一点
SELECT TOP (1)
*
FROM Items i1
JOIN Items i2 ON i2.Name > i1.Name
JOIN Items i3 ON i3.Name > i2.Name
JOIN Items i4 ON i4.Name > i3.Name
JOIN Items i5 ON i5.Name > i4.Name
JOIN Items i6 ON i6.Name > i5.Name
CROSS APPLY (VALUES (
i1.A + i2.A + i3.A + i4.A + i5.A + i6.A,
i1.B + i2.B + i3.B + i4.B + i5.B + i6.B
)) v(TotalA, TotalB)
WHERE TotalA > 150
ORDER BY
TotalB;
Name
in this case is just a proxy for some unique column
可能有更有效的解决方案,具体取决于您的具体问题。
我被困在 select 查询中以从 table 中获得最佳匹配,如下所示:
Name | A | B | TotalA | TotalB |
---|---|---|---|---|
Name1 | 10 | 1 | 10 | 1 |
Name2 | 15 | 2 | 25 | 3 |
Name3 | 20 | 3 | 45 | 6 |
Name4 | 25 | 4 | 70 | 10 |
Name5 | 30 | 5 | 100 | 15 |
Name6 | 35 | 6 | 135 | 21 |
Name7 | 51 | 7 | 175 | 28 |
..... | .... | ...... | ...... | ...... |
..... | .... | ...... | ...... | ...... |
我试图找到 B 总和最低的最佳 6 条记录,但还有一个附加条件,即 A 总和需要高于 150。
这个table按B排序,最好的结果在最前面。因此,6 个最佳结果中 B 的总和为 21,但在这种情况下,A 的总和为 135,低于 150。因此应排除记录 nb 6,并应包括下一个 nb 7。所以最好的结果是记录1-5和记录7中B的总和=22,而A的总和是151,这就足够了。
我使用带分区和顺序的排名函数,但每次查询都返回 0 条记录。是否有可能排除第 6 条记录并将结果取 7,因此 A 的总和将 > 150?
这似乎是 knapsack problem 的一个变体,它是 NP-Complete,最简单的(编码)解决方案就是强制执行每个排列。
鉴于你有固定数量的项目,你可以通过自加入来做到这一点
SELECT TOP (1)
*
FROM Items i1
JOIN Items i2 ON i2.Name > i1.Name
JOIN Items i3 ON i3.Name > i2.Name
JOIN Items i4 ON i4.Name > i3.Name
JOIN Items i5 ON i5.Name > i4.Name
JOIN Items i6 ON i6.Name > i5.Name
CROSS APPLY (VALUES (
i1.A + i2.A + i3.A + i4.A + i5.A + i6.A,
i1.B + i2.B + i3.B + i4.B + i5.B + i6.B
)) v(TotalA, TotalB)
WHERE TotalA > 150
ORDER BY
TotalB;
Name
in this case is just a proxy for some unique column
可能有更有效的解决方案,具体取决于您的具体问题。