SQL选择表中的某些行,以便它们总和到某个值

Jav*_* C. 10 mysql select sum

如何在下表中仅选择一些行,以便它们总和到某个值?

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)

不明白的选项更加棘手; 它是可行的,但你使用存储过程会好得多.


Mos*_*cho 7

让我们这样说:如果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)

请享用!