要查询的SUM查询,直到SUM(users_count)达到1000

时间:2011-08-17 18:08:43

标签: mysql sql select sum

我需要一个sql查询来从我的消息队列中选择行,直到SUM(users_count)达到最多1000个。但是如果只返回一行并且该行的users_count是,则没有问题大于1000。

我需要类似的东西:(我添加了自己的关键字)

SELECT * FROM `messages_queue` UNTIL SUM(users_count) < 1000 AT LEAST 1 ROW

这是我的表结构:

  

messages_queue
     - msg_id
     - msg_body
     - users_count(消息接收者的数量)
     - 时间(插入时间)

5 个答案:

答案 0 :(得分:14)

此解决方案将执行累计和,当总和超过1000时停止:

SELECT NULL AS users_count, NULL AS total
  FROM dual
 WHERE (@total := 0)
 UNION
SELECT users_count, @total := @total + users_count AS total
  FROM messages_queue
 WHERE @total < 1000;

这意味着如果你有两个值,比如800,总和将是1600.第一个SELECT只是初始化@total变量。

如果你想防止总和超过1000,除了单行的值大于1000的情况,那么我认为这是有效的,尽管你需要对它进行一些严格的测试:< / p>

SELECT NULL AS users_count, NULL AS total, NULL AS found
  FROM dual
 WHERE (@total := 0 OR @found := 0)
 UNION
SELECT users_count, @total AS total, @found := 1 AS found
  FROM messages_queue
 WHERE (@total := @total + users_count)
   AND @total < 1000
 UNION
SELECT users_count, users_count AS total, 0 AS found
  FROM messages_queue
 WHERE IF(@found = 0, @found := 1, 0);

答案 1 :(得分:2)

我认为您正在寻找这样的事情:

SELECT *
FROM
   (SELECT 
        *
      , (select sum(users_count) from `messages_queue` where time <= mq.time) RunningTotal       
   FROM `messages_queue` mq) mq2
WHERE mq2.RunningTotal < 1000

答案 2 :(得分:2)

我试图将此作为对Mike答案的评论添加,但是,对于变量的@符号存在问题。

要利用Mike的答案,通过初始化FROM子句中的变量,实际上可以缩短查询,例如:

SELECT users_count, @total := @total + users_count AS total
    FROM (messages_queue, (select @total := 0) t)
WHERE @total < 1000;

答案 3 :(得分:1)

对于纯粹的SQL解决方案感谢Aducci,但正如Thomas Berger所说,这可能最终成为一个非常昂贵的查询。根据表的大小,存储过程可能是更好的方法:

CREATE PROCEDURE messages_to_send
BEGIN
  DECLARE done INT DEFAULT 0;
  DECLARE oldest_date DATETIME;
  DECLARE cur_count INT;
  DECLARE que_size INT DEFAULT 0;
  DECLARE curs CURSOR FOR SELECT users_count, time FROM messages_que ORDER BY time;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

  OPEN curs;

  read_loop: LOOP
    FETCH curs INTO cur_count, oldest_date;
    IF done THEN
      LEAVE read_loop;
    END IF;
    que_size = que_size + cur_count
    IF que_size >= 1000
      LEAVE read_loop;
    END IF;
  END LOOP;

  CLOSE curs

  SELECT * FROM messages_que WHERE time < oldest_date;
END

CALL messages_to_send(); --> returns a result set of messages to send with a total user_count of 1000 or less

答案 4 :(得分:0)

我认为你不能通过一个简单的MySQL查询来实现这个目标。

您必须使用应用程序中的存储过程或过滤器。

修改

我不是MySQL Guru(只能在oracle和postgres上编写存储过程),但你可以从这里开始:http://www.mysqltutorial.org/sql-cursor-in-stored-procedures.aspx

有关语法的更多常规信息位于此处:http://dev.mysql.com/doc/refman/5.0/en/create-procedure.html