3

我有一个带有数据的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:(邮件的当前状态)
  • 分配给:(电子邮件分配给的用户名)
  • 分配时间:(分配电子邮件的日期和时间)
  • logtime:(插入行的日期和时间,即当前状态的日期和时间)

id 4338 和 5731 分别是 mailid 14928 和 15710 的第一行,这些 id 的最后一行是 16300 和 16291,它们的当前状态始终为“已回复”。

在这里,我需要其中的输出

(4352 的日志时间 - 4338 的日志时间)+(16300 的日志时间 - 16297 的日志时间)

这将给我 user1 在 mailid 14928 上花费的时间。

这里有什么共同点:

  1. 最后一行的当前状态列将始终被“回复”
  2. 在 currentstatus 中用前面的“assigned”减去每一行

表格如何更新:

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

在以下两种情况下,都为用户分配了电子邮件(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 秒。我如何优化此查询的任何建议

4

3 回答 3

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 成员!

于 2013-05-01T14:56:07.297 回答
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)

这将花费更少的时间,并且会为您工作。

于 2013-05-01T09:20:19.830 回答
0

I have got the answer, however, need to optimize this query.

    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;

Apologies, could not create a fiddle since facing problems with http://sqlfiddle.com

This query takes approx 150 seconds for 16,000 rows. Any suggestions how i can optimize this query

于 2013-04-29T08:24:17.957 回答