计算用户会话数

时间:2014-09-23 16:44:57

标签: mysql sql

我有一张带有ip的表和一个查看日期,以及一个有网站ID的网站

+------------+-----------+---------------------+
| website_id | ip        | view_date           |
+------------+-----------+---------------------+
| 123        | 123123123 | 2014-01-01 10:23:00 |
+------------+-----------+---------------------+
| 123        | 987987987 | 2014-01-01 10:23:00 |
+------------+-----------+---------------------+
| 123        | 123123123 | 2014-01-01 10:26:00 |
+------------+-----------+---------------------+
| 123        | 987987987 | 2014-01-01 10:24:00 |
+------------+-----------+---------------------+
| 123        | 987987987 | 2014-01-01 10:25:00 |
+------------+-----------+---------------------+
| 123        | 123123123 | 2014-01-02 03:23:00 |
+------------+-----------+---------------------+

我想从表中获取会话,这是有人在网站上开始直到完成的时间。要查看完成的时间,在查看view_date之后的两个查看日期之一之后,有30分钟或更长时间没有活动。

因此,对于此示例数据,我有2个用户123123123987987987

  • 用户123123123有2个会话,因为第3行发生在第1行30分钟,第6行发生在第3行后30分钟
  • 用户987987987有1个会话,因为第4行发生在第2行后不到30分钟,第5行发生在第4行后不到30分钟

我不知道如何使用MySQL来计算它。我所知道的是按ip,然后按view_date对数据进行排序。之后我迷路了。

当我说会话时我的意思是:

  

专门用于特定活动的一段时间。

而不是:

  

一种在多个网页之间跟踪人员的方式。

期望的输出:

+------------+-----------+----------+
| website_id | ip        | sessions |
+------------+-----------+----------+
| 123        | 123123123 | 2        |
+------------+-----------+----------+
| 123        | 987987987 | 1        |
+------------+-----------+----------+

4 个答案:

答案 0 :(得分:1)

SET @a := null;
SET @b := null;
SET @c := null;
SELECT website_id, ip, view_date, COUNT(counting) as num_sessions
FROM
(   SELECT website_id, ip, view_date, 
        @c := if(@a = ip AND @b BETWEEN view_date - interval 30 minute AND view_date, @c + 1, 1) as counting, 
        @a := ip, @b := view_date
    FROM
    (   SELECT * 
        FROM sessions
        ORDER BY ip, view_date
    )t
)t1
WHERE counting = 1
GROUP BY ip;

DEMO

答案 1 :(得分:1)

select ip, sum(session) + 1 as session
from (
    select
    t.*,
    if(@previp = ip and timestampdiff(minute, @prevview, view_date) >= 30, 1, 0) as session,
    @previp := ip,
    @prevview := view_date
    from
    Table1 t
    , (select @prevview := (select view_date from Table1 order by ip, view_date limit 1), 
       @previp := null) var_init_subquery
    order by ip, view_date
) sq
group by ip

答案 2 :(得分:1)

这是我的解决方案

我会计算一下在日期和日期-30分钟之间发生的给定网站ID和IP地址的行数。如果它的0分配1意味着它的新会话,则给它一个0.然后做一个总和。

<强> SQL Fiddle Demo

select website_id,
    ip,
    sum(newSession) as Sessions
from
(select *,
case 
    when (select count(*) 
          from yourTable ytb 
          where ytb.website_id = yta.website_id 
          and ytb.ip = yta.ip 
          and ytb.view_date < yta.view_date 
          and ytb.view_date > date_add(yta.view_date, INTERVAL -30 MINUTE)) = 0 then 1
    else 0
end as newSession
from yourtable yta) baseTable
GROUP BY website_id, ip

答案 3 :(得分:-1)

根据时间和IP排序后,您可以使用游标查找会话总数。您可以从here获取有关mysql游标的更多信息。

更多详情:

CREATE PROCEDURE curdemo()
BEGIN
  DECLARE done INT DEFAULT FALSE;
  DECLARE i INT;
  DECLARE prev_i INT;
  DECLARE d DATE;
  DECLARE prev_d DATE;
  DECLARE cur1 CURSOR FOR SELECT ip, view_date FROM table;
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

  OPEN cur1;

  read_loop: LOOP
    IF prev_i == NULL THEN
        FETCH cur1 INTO prev_i, prev_d;
    END IF;
    FETCH cur1 INTO i, d;
    IF done THEN
      LEAVE read_loop;
    END IF;
    IF prev_i == i && INTERVAL_BETWEEN(prev_d, d) > 30min THEN
      ADD_IN_SESSIONS_FOR_i ;
    END IF;
    prev_i = i;
    prev_d = d;
  END LOOP;

  CLOSE cur1;
END;