简体   繁体   中英

MySQL limit by sum

I want to limit my SELECT results in mySQL by sum. For Example, this is my table:

(id, val)

Data Entries: (1,100), (2,300), (3,50), (4,3000)

I want to select first k entries such that the sum of val in those entries is just enough to make it to M. For example, I want to find entries such that M = 425. The result should be (1,100),(2,300),(3,50).

How can I do that in a mysql select query?

Try this variant -

SET @sum = 0;
SELECT id, val FROM (
  SELECT *, @sum:=@sum + val mysum FROM mytable2 ORDER BY id
) t
WHERE mysum <= 450;

+------+------+
| id   | val  |
+------+------+
|    1 |  100 |
|    2 |  300 |
|    3 |   50 |
+------+------+

This stored procedure might help:

DELIMITER ;;

CREATE PROCEDURE selectLimitBySum (IN m INT)
BEGIN
DECLARE mTmp INT DEFAULT 0;
DECLARE idTmp INT DEFAULT 0;
DECLARE valTmp INT DEFAULT 0;
DECLARE doneLoop SMALLINT DEFAULT 0;
DECLARE crsSelect CURSOR FOR SELECT id, val FROM test3;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET doneLoop = 1;
OPEN crsSelect;
aloop: LOOP
    SET idTmp = 0;
    SET valTmp = 0;
    FETCH crsSelect INTO idTmp, valTmp;
    if doneLoop THEN
        LEAVE aloop;
    END IF;
    SELECT idTmp, valTmp;
    SET mTmp = mTmp + valTmp;
    if mTmp > m THEN
        LEAVE aloop;
    END IF;
END LOOP;
CLOSE crsSelect;
END ;;

DELIMITER ;

Please feel free to change the table names or variable names as per your needs.

from mysql reference manual:

The LIMIT clause can be used to constrain the number of rows returned by the SELECT statement. LIMIT takes one or two numeric arguments, which must both be nonnegative integer constants (except when using prepared statements).

So you cannot use limit the way you proposed. To achieve what you want you need to use your application (java, c, php or whatever else), read the result set row by row, and stop when your condition is reached.

or you can use a prepared statement, but anyway you cant have conditional limit (it must be a constant value) and it is not exactly what you asked for.

create table #limit(
id int,
val int
)

declare @sum int, @id int, @val int, @m int;
    set @sum=0;
    set @m=250; --Value of an entry
    declare limit_cursor cursor for
    select id, val from your_table order by id
    open limit_cursor
    fetch next from limit_cursor into @id, @val
    while(@@fetch_status=0)
    begin
        if(@sum<@m)
        begin
            set @sum = @sum+@val;
            INSERT INTO #limit values (@id, @val);
            fetch next from limit_cursor into @id, @val
        end
    else 
    begin
    goto case1; 
    end
    end
    case1:
    close limit_cursor
    deallocate limit_cursor
    select * from #limit
    truncate table #limit

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