【问题标题】:Calculate delta(difference of current and previous row) mysql group by specific column按特定列计算增量(当前行和上一行的差)mysql组
【发布时间】:2014-07-22 08:58:27
【问题描述】:

我有一个表,例如: 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 是时间戳之间的差异 我想要的是前一行和当前行由 user_id 分组的 Delta Timestamp(以天为单位)的结果。

这应该是结果:

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 我没有找到任何解决方案

希望有人可以帮助我。

【问题讨论】:

标签: mysql sql timestamp datediff difference


【解决方案1】:

试试这个:

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 和相邻的日期时间条目上将您的表连接到自身并计算差异。

【讨论】:

  • 请注意,此解决方案不能很好地扩展。
【解决方案2】:

虽然你在这里选择了一个答案,但这是实现它的另一种方式

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

【讨论】:

    【解决方案3】:

    如果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 子句中的变量可能不会按照我们期望的顺序进行评估。这可以修复,但它会使查询复杂化,这通常会起作用。 )

    【讨论】:

    • "使用变量——你有什么想法?请给我们一个提示。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-14
    • 1970-01-01
    • 2021-10-27
    • 1970-01-01
    • 2017-02-01
    • 1970-01-01
    相关资源
    最近更新 更多