获取每周的响应时间

时间:2014-08-15 20:56:51

标签: mysql sql join group-by

我有3张桌子:

CREATE TABLE `ticket` (
  `tid` int(11) NOT NULL AUTO_INCREMENT,
  `sid` varchar(50) NOT NULL,
  `open_date` datetime NOT NULL,
  PRIMARY KEY (`tid`),
  KEY `sid` (`sid`,`open_date`),
  KEY `open_date` (`open_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `ticket_reply` (
  `rid` int(11) NOT NULL AUTO_INCREMENT,
  `tid` int(11) NOT NULL,
  `reply_date` datetime NOT NULL,
  PRIMARY KEY (`rid`),
  KEY `tid` (`tid`,`reply_date`),
  KEY `reply_date` (`reply_date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `subscription` (
  `sid` varchar(50) NOT NULL,
  `response_time` int(11) NOT NULL DEFAULT '24',
  PRIMARY KEY (`sid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

我正在尝试获取第一张故障单回复的响应时间总和,从故障单打开时将其分组并按DAYNAME分组(也可能是MONTH)。目前我有这个SQL:

SELECT
     t.tid,
    DAYNAME(t.open_date) AS day_opened,
    SUM(TIMESTAMPDIFF(MINUTE, t.open_date, tr.reply_date)) AS num_min,
    SUM(s.response_time * 60) AS response_time_min
FROM ticket t
INNER JOIN ticket_reply tr ON tr.tid = t.tid
INNER JOIN subscription s ON s.sid = t.sid
GROUP BY 
    t.tid #group by tid as ticket_reply may return many
ORDER BY t.open_date DESC;

所以我的第一个挑战是获得第一个由GROUP BY解决的ticket_reply行,我试图在连接中获得一个子查询,但它仍然为每个ticket_reply行返回一行。

所以现在我想开始按DAYNAME分组,也许MONTH,但如果我将它添加到GROUP BY,它就不会分组:

GROUP BY
   t.tid,
   DAYNAME(t.open_date)

在tid之前尝试了DAYNAME,但这没有任何区别。

所以我有几个问题,是否有更好的方法来获取ticket_reply中的第一行然后按DAYNAME分组?我有一种感觉,让子查询中的第一行可以修复分组。

1 个答案:

答案 0 :(得分:0)

它是分组,但是因为t.tid子句中有GROUP BY,而tid列中的ticket列是唯一的,所以来自{{1}的多行不会崩溃,每个都会在自己的行上。

您不清楚要返回的结果。

(SELECT列表中的ticket表达式看起来有点奇怪,因为您可以匹配SUM(s.response_time)中的多行。)

鉴于您现有的陈述,看起来您可能希望使用内联视图来返回最早的"每个票证ticket_reply,代替对reply_date表的引用。

ticket_reply

(不幸的是,实现内联视图(填充和访问中间"派生表")可能是性能问题的根源。)

作为另一种选择,您可以考虑在 JOIN /*ticket_reply*/ ( SELECT r.tid , MIN(r.reply_date) AS reply_date FROM ticket_reply r GROUP BY r.tid ) tr ON tr.tid = t.tid 列表中使用相关子查询,而不是执行JOIN操作。也就是说,代替SELECT的引用,您可以执行以下操作:

tr.reply_date

并删除JOIN到 (SELECT MIN(r.reply_date) FROM ticket_reply r WHERE r.tid = t.tid) 表。

但是,重复执行该子查询(对于返回的每一行一次),也可能是大型集的性能问题。


但是"大"问题是,您是否需要为匹配的ticket_reply的每次匹配添加s.response_time(正如您当前的查询所做的那样),或者您是否只需要为每个ticket_reply添加一次s.response_time {1}}?

也就是说,如果给定的ticket有三ticket_reply,我们是否需要"三倍"我们添加到行的ticket的值?

如果您需要在每个`ticket_reply的总数中包含response_time,那么:

response_time

如果您只需要在每个SELECT DAYNAME(t.open_date) AS day_opened , SUM(TIMESTAMPDIFF(MINUTE, t.open_date, tr.reply_date)) AS num_min , SUM(s.response_time) * 60 * tr.cnt_replies AS response_time_min FROM ticket t JOIN ( SELECT r.tid , MIN(r.reply_date) AS reply_date , COUNT(1) AS cnt_replies FROM ticket_reply r GROUP BY r.tid ) tr ON tr.tid = t.tid JOIN subscription s ON s.sid = t.sid GROUP BY day_opened 的总计中包含response_time,请删除对ticket的引用:

cnt_replies

SELECT DAYNAME(t.open_date) AS day_opened , SUM(TIMESTAMPDIFF(MINUTE, t.open_date, tr.reply_date)) AS num_min , SUM(s.response_time) * 60 AS response_time_min FROM ticket t JOIN ( SELECT r.tid , MIN(r.reply_date) AS reply_date FROM ticket_reply r GROUP BY r.tid ) tr ON tr.tid = t.tid JOIN subscription s ON s.sid = t.sid GROUP BY day_opened 个月,只需更改SELECT列表中的第一个表达式,以及GROUP BY子句中的引用。