如何在下表中仅选择一些行,以便它们总和到某个值?
Table
-----
id | qty1 | qty2 | qty3 | qty4
------------------------------
1 | 0.0 | 0.0 | 10 | 20
2 | 1.5 | 0.0 | 7.5 | 18
3 | 1.0 | 2.0 | 7.5 | 18
4 | 0.0 | 0.5 | 5 | 13
Run Code Online (Sandbox Code Playgroud)
比方说,我想要的最高价值是57 ......
所以我需要选择上一个表中的行,使得每行的qty1 + qty2 + qty3 + qty4,直到该57值,并丢弃其他行.在这个例子中,我会得到以下内容:
id | qty1 | qty2 | qty3 | qty4
------------------------------
1 | 0.0 | 0.0 | 10 | 20
2 | 1.5 | 0.0 | 7.5 | 18
Run Code Online (Sandbox Code Playgroud)
因为10 + 20 + 1.5 + 7.5 + 18 = 57,所以我丢弃第3和第4行......
现在我希望最高值为50,那么我应该得到:
id | qty1 | qty2 | qty3 | qty4
------------------------------
1 | 0.0 | 0.0 | 10 | 20
2 | 1.5 | 0.0 | 7.5 | 11
Run Code Online (Sandbox Code Playgroud)
由于这些值总和为50,而第7行从第2行开始,qty4被省略......(顺便说一句,行以这种特殊方式排序,因为这是我想要考虑qtys总和的顺序......它是例如,无法总结第一行1,然后是3,然后是2,然后是4 ......它们应该始终按照1,2,3,4的顺序进行调整......)
如果我想补充这个怎么办?我的意思是,在最后一个结果中没有得到的另外两行.
第一种情况:
id | qty1 | qty2 | qty3 | qty4
------------------------------
3 | 1.0 | 2.0 | 7.5 | 18
4 | 0.0 | 0.5 | 5 | 13
Run Code Online (Sandbox Code Playgroud)
第二种情况:
id | qty1 | qty2 | qty3 | qty4
------------------------------
2 | 0.0 | 0.0 | 0.0 | 7
3 | 1.0 | 2.0 | 7.5 | 18
4 | 0.0 | 0.5 | 5 | 13
Run Code Online (Sandbox Code Playgroud)
(如果第二种情况太复杂,那么如何获得:
id | qty1 | qty2 | qty3 | qty4
------------------------------
1 | 0.0 | 0.0 | 10 | 20
Run Code Online (Sandbox Code Playgroud)
因为将第2行的原始qtys相加会超过50的值,所以我将其丢弃......在这种情况下的补码应该是:
id | qty1 | qty2 | qty3 | qty4
------------------------------
2 | 1.5 | 0.0 | 7.5 | 18
3 | 1.0 | 2.0 | 7.5 | 18
4 | 0.0 | 0.5 | 5 | 13
Run Code Online (Sandbox Code Playgroud)
)
rua*_*akh 13
括号中的简化选项也不错:
SELECT foo1.*
FROM foo AS foo1
JOIN foo AS foo2
ON foo2.id <= foo1.id
GROUP
BY foo1.id
HAVING SUM(foo2.qty1 + foo2.qty2 + foo2.qty3 + foo2.qty4) <= 57
;
Run Code Online (Sandbox Code Playgroud)
(你没有提到桌子的名字,所以我去了foo.)
补充将是:
SELECT *
FROM foo
WHERE id NOT IN
( SELECT foo1.id
FROM foo AS foo1
JOIN foo AS foo2
ON foo2.id <= foo1.id
GROUP
BY foo1.id
HAVING SUM(foo2.qty1 + foo2.qty2 + foo2.qty3 + foo2.qty4) <= 57
)
;
Run Code Online (Sandbox Code Playgroud)
不明白的选项更加棘手; 它是可行的,但你使用存储过程会好得多.
让我们这样说:如果SQL是一种宗教信仰,那么我就会提供这种解决方案.SQL并不是要解决这类问题,所以任何解决方案都会很糟糕.我也不例外:)
set @limitValue := 50;
select id, newQty1, newQty2, newQty3, newQty4 from (
select id,
if(@limitValue - qty1 > 0, qty1, greatest(@limitValue, 0)) newQty1,
@limitValue := @limitValue - qty1 Total1,
if(@limitValue - qty2 > 0, qty2, greatest(@limitValue, 0)) newQty2,
@limitValue := @limitValue - qty2 Total2,
if(@limitValue - qty3 > 0, qty3, greatest(@limitValue, 0)) newQty3,
@limitValue := @limitValue - qty3 Total3,
if(@limitValue - qty4 > 0, qty4, greatest(@limitValue, 0)) newQty4,
@limitValue := @limitValue - qty4 Total4
from (
select id, qty1, qty2, qty3, qty4,
@rowTotal < @limitValue Useful,
@previousRowTotal := @rowTotal PreviousRowTotal,
@rowTotal := @rowTotal + qty1 + qty2 + qty3 + qty4 AllRowsTotal,
@rowTotal - @previousRowTotal CurrentRowTotal
from t,
(select @rowTotal := 0, @previousRowTotal := 0) S1
) MarkedUseful
where useful = 1
) Final
Run Code Online (Sandbox Code Playgroud)
对于提供的数据,结果如下:
+----+---------+---------+---------+---------+
| ID | NEWQTY1 | NEWQTY2 | NEWQTY3 | NEWQTY4 |
+----+---------+---------+---------+---------+
| 1 | 0 | 0 | 10 | 20 |
| 2 | 1.5 | 0 | 7.5 | 11 |
+----+---------+---------+---------+---------+
Run Code Online (Sandbox Code Playgroud)
补充:
set @limitValue := 50;
select t1.id,
coalesce(t1.qty1 - newQty1, t1.qty1) newQty1,
coalesce(t1.qty2 - newQty2, t1.qty2) newQty2,
coalesce(t1.qty3 - newQty3, t1.qty3) newQty3,
coalesce(t1.qty4 - newQty4, t1.qty4) newQty4
from t t1 left join (
select id,
if(@limitValue - qty1 > 0, qty1, greatest(@limitValue, 0)) newQty1,
@limitValue := @limitValue - qty1 Total1,
if(@limitValue - qty2 > 0, qty2, greatest(@limitValue, 0)) newQty2,
@limitValue := @limitValue - qty2 Total2,
if(@limitValue - qty3 > 0, qty3, greatest(@limitValue, 0)) newQty3,
@limitValue := @limitValue - qty3 Total3,
if(@limitValue - qty4 > 0, qty4, greatest(@limitValue, 0)) newQty4,
@limitValue := @limitValue - qty4 Total4
from (
select id, qty1, qty2, qty3, qty4,
@rowTotal < @limitValue Useful,
@previousRowTotal := @rowTotal PreviousRowTotal,
@rowTotal := @rowTotal + qty1 + qty2 + qty3 + qty4 AllRowsTotal,
@rowTotal - @previousRowTotal CurrentRowTotal
from t,
(select @rowTotal := 0, @previousRowTotal := 0) S1
) MarkedUseful
where useful = 1
) Final
on t1.id = final.id
where Total1 < 0 or Total2 < 0 or Total3 < 0 or Total4 < 0 or final.id is null
Run Code Online (Sandbox Code Playgroud)
对于提供的数据,结果如下:
+----+---------+---------+---------+---------+
| ID | NEWQTY1 | NEWQTY2 | NEWQTY3 | NEWQTY4 |
+----+---------+---------+---------+---------+
| 2 | 0 | 0 | 0 | 7 |
| 3 | 1 | 2 | 7.5 | 18 |
| 4 | 0 | 0.5 | 5 | 13 |
+----+---------+---------+---------+---------+
Run Code Online (Sandbox Code Playgroud)
请享用!