使用join进行Mysql时间计算

时间:2014-05-16 21:29:06

标签: mysql

我有两张桌子:销售,行动

销售表:

id, datetime, status
--------------------

动作表:

id, datetime, sales_id, action
------------------------------

行动和销售表之间存在多对一关系。对于每个销售记录,可能有许多操作。我试图在一天中的每个小时确定首次创建销售记录与创建与其相应销售记录关联的第一个操作记录之间的平均时差。

换句话说,销售代理响应潜在客户的速度有多快(以小时为单位),这取决于潜在客户当天的工作时间。

这是我试过的:

SELECT

FROM_UNIXTIME(sales.datetime, '%H') as Hour,
count(actions.id) AS actions,
(MIN(actions.datetime) - sales.datetime) / 3600 as Lag

FROM
actions 
INNER JOIN sales ON actions.sales_id = sales.id

group by Hour

我得到了“滞后”的合理小时数,但我不相信它们是准确的:

   Hour Actions Lag
    00  66      11.0442
    01  30      11.2758
    02  50      8.2900
    03  25      5.7492
    .
    .
    .
    23  77      34.4744

我的问题是,这是获取为给定销售记录记录的第一个操作的值的正确方法吗? :

(MIN(actions.createDate) - sales.createDate) / 3600 as Lag

2 个答案:

答案 0 :(得分:1)

应该是:

MIN(actions.datetime - sales.datetime) / 3600 AS Lag

您可以在一小时内从任何销售中获取第一个操作,并从其时间戳中减去每个销售的时间戳。您只需要在ID加入的操作和销售中进行减法。

答案 1 :(得分:0)

此查询有两个图层,它们有助于抓取它们。

最低层应该为sales.datetime的每一行计算从action.datetime到最早sales.的滞后时间。这可能会使用MIN()函数。

下一层将计算这些滞后时间的统计数据,按一天中的小时计算在最低层。这将使用AVG()函数。

这是最低层:

 SELECT s.id, s.datetime, s.status,
        TIMEDIFF(SECOND, MIN(a.datetime), s.datetime) AS lag_seconds
   FROM sales AS s
   JOIN actions AS a ON s.id = a.sales_id AND a.datetime > s.datetime
  GROUP BY s.id, s.datetime, s.status

ON子句的第二部分确保您只考虑在输入销售订单后执行的操作。这可能是不必要的,但我想我会把它丢进去。

这是第二层。

 SELECT HOUR(datetime) AS hour_Sale_entered, 
        COUNT(*) AS number_in_that_hour,
        AVG(lag_seconds) / 3600.0 AS Lag_to_first_action
   FROM (
          SELECT s.id, s.datetime, s.status,
                TIMEDIFF(SECOND, MIN(a.datetime), s.datetime) AS lag_seconds
           FROM sales AS s
           JOIN actions AS a ON s.id = a.sales_id AND a.datetime > s.datetime
          GROUP BY s.id, s.datetime, s.status
        ) AS d
  GROUP BY HOUR(datetime)
  ORDER BY HOUR(datetime) 

了解如何进行两次嵌套聚合(GROUP BY)操作?内部标识第一个动作,第二个动作标识每小时平均值。

还有一个小问题。如果您想要包含尚未采取行动的sales项,您可以执行以下操作:

 SELECT HOUR(datetime) AS hour_Sale_entered, 
        COUNT(*) AS number_in_that_hour,
        SUM(no_action) AS not_acted_upon_yet,
        AVG(lag_seconds) / 3600.0 AS Lag_to_first_action
   FROM (
          SELECT s.id, s.datetime, s.status,
                TIMEDIFF(SECOND, MIN(a.datetime), s.datetime) AS lag_seconds,
                IFNULL(a.id,1,0) AS no_action
           FROM sales AS s
           LEFT JOIN actions AS a ON s.id = a.sales_id AND a.datetime > s.datetime
          GROUP BY s.id, s.datetime, s.status
        ) AS d
  GROUP BY HOUR(datetime)
  ORDER BY HOUR(datetime) 

lag_seconds的平均值仍然是正确的,因为没有sales行的action行将具有NULL值,而AVG()忽略空值。