0

我有以下记录用户访问时间的mysql表:

在此处输入图像描述

我想更新 visit_id 以便“访问”是同一用户的一组条目,其中没有条目在前一个之后超过 20 分钟,并且每个条目的 visit_id 是该访问的第一个条目的 visit_id .

我希望这个例子有助于说明清楚。更新后,上面的示例表应该变成:

在此处输入图像描述

如果上一个条目发生在不到 20 分钟之前,我可以创建一个更新,将 visit_id 设置为该用户的上一个条目的 visit_id。

但是我无法解决如何创建仅 sql 更新来处理“级联”效应,换句话说,visit_id 需要找到该 user_id 的最早条目,该条目发生在 20 分钟的间隙之前。它可能是那个条目的 visit_id(如果它是那个访问的第一个),或者是前一个条目的 visit_id,或者是前一个前一个条目,或者前一个前一个前一个前一个条目,等等。

我怎么能写这个更新?

4

1 回答 1

0

试试这个查询(但不要在生产数据上尝试,而是在这个数据的副本上尝试):

update tabb_after_update tabb, 
(
   select t.*,
       ( SELECT min( visit_id )
         FROM tabb_after_update t1
         WHERE t1.user_id = t.user_id
         AND t1.time_of_visit <= t.time_of_visit
         AND t1.time_of_visit >= subtime( t.time_of_visit, '00:20' )
        ) new_id
    from tabb_after_update t
) tabb1
SET tabb.visit_id = tabb1.new_id
WHERE tabb.user_id = tabb1.user_id
  AND tabb.visit_id = tabb1.visit_id
;

SQLFiddle 演示 --> http://www.sqlfiddle.com/#!2/caa08/1




------ 编辑 -----

如果间隙 <= 20 分钟,另一个版本“将间隙连接”到一个组中。

set @last_uid = 0;
set @last_tm = '00:00';
set @last_vid = 0;
update tabb_after_update tabb, 
(
        select t.* ,
               case when @last_uid = user_id 
                         AND cast( @last_tm as time) >= subtime( time_of_visit, '00:20' )
                    then if( (@last_tm := time_of_visit ), @last_vid, @last_vid )
                    else 
                         if( (@last_uid := user_id) + 
                             (@last_vid := visit_id ) +
                             (@last_tm := time_of_visit ),
                             @last_vid, @last_vid )
               end new_id
        from tabb_after_update t
        order by user_id, time_of_visit
) tabb1
SET tabb.visit_id = tabb1.new_id
WHERE tabb.user_id = tabb1.user_id
  AND tabb.visit_id = tabb1.visit_id
;

SQLFiddle 演示 --> http://www.sqlfiddle.com/#!9/39f03/1
在此演示中,用户 1 的条目从 17:10 到 17:50 之间的“间隔”记录少于 20 分钟,并且该查询将所有这些记录“组合”成一组。

于 2013-08-26T11:11:34.643 回答