简体   繁体   English

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

[英]Calculate delta(difference of current and previous row) mysql group by specific column

I have a table like : session is the name of the table for example With columns: Id, sessionDate, user_id 我有一个像这样的表:session是表的名称,例如列:Id,sessionDate,user_id

What i need: Delta should be a new calculated column 我需要的是: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 is the Difference between the timestamps What i want is a result for Delta Timestamp (in Days) for the the previous row and the current row grouped by the user_id. Delta是时间戳之间的差异我想要的是上一行的Delta Timestamp(以天为单位)和user_id分组的当前行的结果。

this should be the result: 这应该是结果:

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

I already have a solution for a specific user_id: 我已经有一个特定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

But for more user_ids i didn´t find any solution 但是对于更多user_ids我找不到任何解决方案

Hope somebody can help me. 希望有人可以帮助我。

Try this: 尝试这个:

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)

Which means: join your table to itself on user_ids and adjacent datetime entries and compute the difference. 这意味着:在user_ids和相邻的datetime条目上将表连接到自身并计算差异。

If id is really sequential (as in your sample data), the following should be quite efficient: 如果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;

There is also another efficient method using variables. 还有另一种使用变量的有效方法。 Something like this should work: 这样的事情应该有效:

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;

(There is a small issue with these queries where the variables in the select clause may not be evaluated in the order we expect them to. This is possible to fix, but it complicates the query and this will usually work.) (这些查询存在一个小问题,其中select子句中的变量可能无法按照我们期望的顺序进行评估。这可以修复,但它会使查询复杂化,这通常会起作用。)

Although you have choosen an answer here is another way of achieving it 虽然你在这里选择了答案,但另一种方法是实现它

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 DEMO

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM