循环遍历mysql表数据

时间:2013-04-29 06:55:34

标签: mysql function select stored-procedures

我有一个带有数据的

的mysql表'table1'
id      mailid  currentstatus   assignedto  assignedtime       logtime
4338    14928   assigned           user1    4/15/2013 13:44    4/15/2013 13:44
4352    14928   followup           user1    4/15/2013 13:44    4/15/2013 13:50
16297   14928   assigned           user1    4/15/2013 13:44    4/29/2013 9:52
16300   14928   replied            user1    4/15/2013 13:44    4/29/2013 9:55
5731    15710   assigned           user2    4/17/2013 10:16    4/17/2013 10:17
5769    15710   followup           user2    4/17/2013 10:16    4/17/2013 10:35
16281   15710   assigned           user2    4/17/2013 10:16    4/29/2013 9:40
16291   15710   replied            user2    4/17/2013 10:16    4/29/2013 9:48

我想知道每个用户在每个mailid上花费的时间。

列的说明:

  • id :(自动增量列)
  • mailid :(电子邮件的唯一ID)
  • currentstatus :(邮件的当前状态)
  • assignto :(分配电子邮件的用户名)
  • assigntime :(分配电子邮件的日期和时间)
  • logtime :(行的插入日期和时间,即当前状态的日期和时间)

id 4338和5731分别是mailid 14928和15710的第一行,这些id的最后一行是16300和16291,它们的currentstatus总是为'replied'。

这里,我需要输出

  

(logtime为4352 - logtime为4338)+(logtime为16300 - logtime of   16297)

这将为我提供user1在mailid 14928上花费的时间。

这里有什么共同点:

  1. 最后一行的currentstatus列始终为'replied'
  2. 要与currentstatus中前面的“已分配”相减的每一行
  3. 表格如何更新:

    这是电子邮件管理解决方案的一部分,其中电子邮件分配给用户,用户可以回复电子邮件或将其放入后续处理并稍后回复。

    在以下两种情况下,都为用户分配了一封电子邮件(14928和15710)。用户都将这些电子邮件放在后续邮件中,当他们不得不回复此电子邮件时,这些电子邮件被重新分配,然后回复。

    请帮忙!

    所需的输出是:

    mailid  assignedto  timespent
    14928   user1       00:08:55
    15710   user2       00:26:57
    

    到目前为止,我能够编写以下查询,但是,需要优化此查询。

    SELECT mailid,
           assignedto,
           sum(st) TimeSpent
    FROM
      ( SELECT b.*,
        CASE WHEN b.currentstatus = 'assigned' 
               THEN TIMESTAMPDIFF(SECOND, b.logtime, (SELECT a.logtime
                                                       FROM inbox_log a
                                                       WHERE a.mailid = b.mailid
                                                       AND a.logtime > b.logtime
                                                       ORDER BY a.table1 LIMIT 1))
               ELSE 0
         END st
       FROM table1 b
       WHERE logtime >= '2013-04-25') d
    GROUP BY mailid,
             assignedto;
    
      道歉,自从面临问题以来,无法创造一个小提琴   http://sqlfiddle.com

    对于16,000行,此查询大约需要150秒。任何建议我如何优化此查询

3 个答案:

答案 0 :(得分:2)

感谢@Chitranjan Thakur,我无法优化查询。下面是我创建的功能。

CREATE DEFINER=`root`@`%` FUNCTION <function-name>(mailidparam INT) RETURNS INT(11)
BEGIN
  DECLARE bdone,
          abc BOOL;
  DECLARE mt VARCHAR(150);
  DECLARE lt DATETIME;
  DECLARE tstart,
          tend DATETIME;
  DECLARE taht INT;
  DECLARE curs CURSOR FOR
  SELECT
    il.currentstatus,
    il.logtime
  FROM table1 il
  WHERE il.mailid = mailidparam
  ORDER BY il.logtime;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET bDone = TRUE;
  OPEN curs;
  SET bDone = FALSE;
  SET taht = 0;
  SET tend = NULL;
read_loop:
LOOP
  FETCH curs INTO mt, lt;
  IF bdone THEN
    LEAVE read_loop;
  END IF;
  IF (mt = 'assigned') THEN
    SET tstart = lt;
  ELSE
    SET tend = lt;
    SET taht := taht + TIMESTAMPDIFF(SECOND, tstart, tend);
  END IF;
END LOOP;
  CLOSE curs;
  RETURN taht;
END$$

DELIMITER ;

和查询

SELECT 
  *,
  get_mailid_aht (il.mailid) aht 
FROM
  table1 il 
WHERE il.currentstatus = 'replied' ;

之前的工作过去需要大约125秒,但是在执行该功能后,它需要大约108秒,这不是一项伟大的成就。

  

但是,添加mailid索引,currentstatus和logtime工作   像魔术一样,现在查询在3.023秒内运行。

感谢StackOverflow成员随时为您提供帮助!

答案 1 :(得分:1)

嘿,您可以使用“功能”来优化它:


首先,您需要创建一个函数,该函数只会导致您想要执行操作的记录。

<强>语法:

CREATE FUNCTION func_name ([func_parameter[,...]]) RETURNS type routine_body

示例

DELIMITER $$
  CREATE FUNCTION hello_world(addressee TEXT)
    RETURNS TEXT
      LANGUAGE SQL -- This element is optional and will be omitted from subsequent examples
    BEGIN
      RETURN CONCAT('Hello ', addressee);
  END;
$$
DELIMITER ;

执行如下:

mysql> SELECT hello_world('Earth');
1 row in set (0.00 sec)

这将花费更少的时间,并将为你工作。

答案 2 :(得分:0)

我得到了答案,但是,需要优化此查询。

    select mailid, assignedto, sum(st) TimeSpent
    from
    (
    SELECT b.*, 
CASE WHEN b.currentstatus = 'assigned' 
   THEN TIMESTAMPDIFF(SECOND, b.logtime, 
     (SELECT a.logtime from inbox_log a 
      where a.mailid = b.mailid AND a.logtime > b.logtime ORDER BY a.table1 LIMIT 1))
  ELSE 0 END st from table1 b where logtime >= '2013-04-25'    
    ) d
    GROUP BY mailid, assignedto;
  道歉,自从面临问题以来,无法创造一个小提琴   http://sqlfiddle.com

对于16,000行,此查询大约需要150秒。任何建议我如何优化此查询