简体   繁体   中英

SQL query to get rows until sum of a column equal to some value

mySchema:

create table Warehouse
(
    ware_id    int,
    weight     int unsigned,
    added_date date
);

insert into Warehouse
values (56, 21, '2008-04-04'),
       (42, 40, '2009-10-13'),
       (10, 11, '2010-11-14'),
       (22, 2, '2010-11-22'),
       (19, 27, '2012-01-25'),
       (80, 14, '2012-01-25'),
       (21, 31, '2012-03-11'),
       (52, 32, '2012-05-30'),
       (49, 4, '2013-02-26'),
       (77, 17, '2013-05-24'),
       (22, 54, '2016-04-18'),
       (40, 19, '2017-02-20');

I have a warehouse that stores many wares in it with restriction in weights.

The sum of all wares must less than or equal to 272.

If a new ware wants to be added and warehouse capacity is full, we must remove the oldest wares in order to make free space for the new one, and this process will be continued until warehouse free-space is equal or greater than new ware weight.

How can I do a simple query to return all of the wares that need to be removed?

For example, if the weight of the new item is 100, the query should return something like this:


| ware_id | weight | added_date |
|---------|--------|------------|
|      56 |     21 | 2008-04-04 |
|      42 |     40 | 2009-10-13 |
|      10 |     11 | 2010-11-14 |
|      22 |      2 | 2010-11-22 |
|      19 |     27 | 2012-01-25 |

SQL Fiddle

If you are running MySQL 8.0, you can do a window sum:

select *
from (
    select
        w.*,
        sum(weight) over(order by added_date desc, ware_id) running_weight
    from Warehouse w
) t
where running_weight > 272
order by added_date desc, ware_id;

The inner query computes a running sum of the weight s, starting with the most recent record, and by descending added_date (we use ware_id to break the ties). The outer query pulls out all the records for which the running sum exceeds 272.

Demo on DB Fiddle

Your initial dataset has a total weight of 272.

Let's add a recent record with a weight of 100.

insert into Warehouse values (99, 100, '2019-11-23');

Now the query returns:

ware_id | weight | added_date | running_weight
------: | -----: | :--------- | -------------:
     19 |     27 | 2012-01-25 |            284
     80 |     14 | 2012-01-25 |            298
     22 |      2 | 2010-11-22 |            300
     10 |     11 | 2010-11-14 |            311
     42 |     40 | 2009-10-13 |            351
     56 |     21 | 2008-04-04 |            372

If you are running in MySQL 5.6 you can do this:

SET @sum = 0;
SELECT ware_id, weight, added_date
FROM (
  SELECT
      ware_id,
      weight,
      added_date,
      (@sum:=@sum + weight) AS sum_weights
  FROM
      Warehouse
  ORDER BY added_date DESC
) as sumed_weights
WHERE sumed_weights.sum_weights > (272 - 100)

Where 100 is the weight of the new item.

SQLFiddle

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM