按特定列计算mysql组的delta(当前行和上一行的差异)

时间:2014-06-02 09:22:38

标签: mysql sql timestamp datediff difference

我有一个表:例如,session是表的名称 使用列:Id,sessionDate,user_id

我需要什么: Delta应该是一个新的计算列

Id | sessionDate          | user_id | Delta in days
------------------------------------------------------
1  | 2011-02-20 00:00:00 |     2    | NULL
2  | 2011-03-21 00:00:00 |     2    | NULL
3  | 2011-04-22 00:00:00 |     2    | NULL
4  | 2011-02-20 00:00:00 |     4    | NULL
5  | 2011-03-21 00:00:00 |     4    | NULL
6  | 2011-04-22 00:00:00 |     4    | NULL

Delta是时间戳之间的差异 我想要的是上一行的Delta Timestamp(以天为单位)和user_id分组的当前行的结果。

这应该是结果:

Id | sessionDate         | user_id | Delta in Days
------------------------------------------------------
1  | 2011-02-20 00:00:00 |     2   | NULL
2  | 2011-02-21 00:00:00 |     2   | 1
3  | 2011-02-22 00:00:00 |     2   | 1
4  | 2011-02-20 00:00:00 |     4   | NULL
5  | 2011-02-23 00:00:00 |     4   | 3
6  | 2011-02-25 00:00:00 |     4   | 2

我已经有针对特定user_id的解决方案:

SELECT user_id, sessionDate, 
abs(DATEDIFF((SELECT MAX(sessionDate) FROM session WHERE sessionDate <  t.sessionDate and user_id = 1), sessionDate)) as Delta_in_days  
FROM session AS t
WHERE t.user_id = 1 order by sessionDate asc

但是对于更多user_ids我找不到任何解决方案

希望有人可以帮助我。

3 个答案:

答案 0 :(得分:2)

试试这个:

drop table a;
create table a( id integer not null primary key, d datetime, user_id integer );
insert into a values (1,now() + interval 0 day, 1 );
insert into a values (2,now() + interval 1 day, 1 );
insert into a values (3,now() + interval 2 day, 1 );
insert into a values (4,now() + interval 0 day, 2 );
insert into a values (5,now() + interval 1 day, 2 );
insert into a values (6,now() + interval 2 day, 2 );

select t1.user_id, t1.d, t2.d, datediff(t2.d,t1.d)
from a t1, a t2
where t1.user_id=t2.user_id
and t2.d = (select min(d) from a t3 where t1.user_id=t3.user_id and t3.d > t1.d)

这意味着:在user_ids和相邻的datetime条目上将表连接到自身并计算差异。

答案 1 :(得分:1)

如果id确实是连续的(如您的示例数据中所示),则以下内容应非常有效:

select t.id, t.sessionDate, t.user_id, datediff(t2.sessiondate, t.sessiondate)
from table t left outer join
     table tprev
     on t.user_id = tprev.user_id and
        t.id = tprev.id + 1;

还有另一种使用变量的有效方法。这样的事情应该有效:

select t.id, t.sessionDate, t.user_id, datediff(prevsessiondate, sessiondate)
from (select t.*,
             if(@user_id = user_id, @prev, NULL) as prevsessiondate,
             @prev := sessiondate,
             @user_id := user_id
      from table t cross join
           (select @user_id := 0, @prev := 0) vars
      order by user_id, id
     ) t;

(这些查询存在一个小问题,select子句中的变量可能无法按照我们期望的顺序进行评估。这可以修复,但它会使查询复杂化,这通常会的工作。)

答案 2 :(得分:0)

虽然你已经选择了答案,但另一种方法是实现它

SELECT
t1.Id,
t1.sessionDate,
t1.user_id,
TIMESTAMPDIFF(DAY,t2.sessionDate,t1.sessionDate) as delta
from myTable t1
left join myTable t2
on t1.user_id = t2.user_id
AND t2.Id = (
  select max(Id) from myTable t3
  where t1.Id > t3.Id AND t1.user_id = t3.user_id

);

<强> DEMO