2013-05-03 55 views
0

登录/注销事件记录在一张类似的表格之间的合作:获取小时套日期

user_id  object_id date_event 
7   2   2013-05-03 08:37:11 
7   3   2013-05-03 12:43:51 
7   2   2013-05-03 15:33:41 
7   3   2013-05-03 17:10:01 

有记录的其他对象,但2和3是重要的(2 =登录,3 =登出)。

我有一个查询的麻烦,将显示一个总计的登陆,小时我用this为出发点,但我的查询返回null登录的总时间。

 SELECT 
      el.user_id, 
      TIME(SUM(el.date_event*(1-2*el.object_id))) AS total_time 
     FROM 
      event_log el 
     WHERE 
      DATE(el.date_event) = '2013-05-03' AND 
      el.object_id IN (2,3) AND 
      el.user_id = 9 
     GROUP BY 
      el.user_id; 

这yeilds:

user_id  total_time 
9   NULL 

当我想到

user_id  total_time 
9   05:43:00 

为什么回报IN NULL?数据集中没有空值。

+0

在另一个例子中,当你试图输入你的object_id时,他使用1s和0s,并且你正在使用2s和3s。他使用1和0来设置正面和负面。你的工作不会一样。尝试一个case语句将2变为1,三个变为0. – Leeish 2013-05-03 21:59:29

+0

我不知道这是否能解决它,但我至少可以看到这是您的逻辑不同的地方。 – Leeish 2013-05-03 22:01:42

回答

2

假设3注销和2登录

SELECT T1.user_id, 
     T1.date_event, 
     MIN(TimeDiff((T2.date_event), T1.date_event)) AS DaysDiff 
FROM YourTable T1 
     LEFT JOIN YourTable T2 
      ON T1.user_id = T2.user_id 
      AND T2.date_event > T1.date_event 
WHERE T1.object_id = 2 AND T2.object_id = 3 
GROUP BY T1.user_id, 
     T1.date_event 
+0

目前没有工作,给我一个编辑的机会 – 2013-05-03 22:10:25

+0

这里唯一的问题是它不能很好地处理丢失的数据。例如两个连续登录没有注销。有可能用MySQL来处理但不容易使用 – 2013-05-03 22:10:52

+1

你只需要将TIMEDIFF的参数取反,然后在min之后而不是之前。 [看到这个小提琴](http://sqlfiddle.com/#!2/bf2c0/12)来修复它 – 2013-05-03 22:17:39

2

我有另一种方法

SET @given_user = 7; 
SET @dt = '2013-05-03'; 
SET @dt1 = @dt + INTERVAL 0 SECOND; 
SET @dt2 = @dt + INTERVAL 1 DAY; 
SELECT 
    SEC_TO_TIME(SUM(dts)) TotalTime 
FROM 
(
    SELECT 
     (IF(object_id=2,-1,1) * 
     (UNIX_TIMESTAMP(date_event) - 
     UNIX_TIMESTAMP(DATE(date_event) +INTERVAL 0 SECOND))) dts 
    FROM 
     event_log 
    WHERE 
     [email protected]_user AND 
     object_id IN (2,3) AND 
     date_event >= @dt1 AND 
     date_event < @dt2 
) A; 

这是你的样本数据

use test 
DROP TABLE IF EXISTS event_log; 
CREATE TABLE event_log 
(
    id INT NOT NULL AUTO_INCREMENT, 
    user_id INT NOT NULL, 
    object_id INT NOT NULL, 
    date_event DATETIME, 
    PRIMARY KEY (id) 
); 
INSERT into event_log 
(user_id,object_id,date_event) VALUES 
(7,2,'2013-05-03 08:37:11'), 
(7,3,'2013-05-03 12:43:51'), 
(7,2,'2013-05-03 15:33:41'), 
(7,3,'2013-05-03 17:10:01'); 

这被载入

use test 
Database changed 
mysql> DROP TABLE IF EXISTS event_log; 
Query OK, 0 rows affected (0.00 sec) 

mysql> CREATE TABLE event_log 
    -> (
    ->  id INT NOT NULL AUTO_INCREMENT, 
    ->  user_id INT NOT NULL, 
    ->  object_id INT NOT NULL, 
    ->  date_event DATETIME, 
    ->  PRIMARY KEY (id) 
    ->); 
Query OK, 0 rows affected (0.05 sec) 

mysql> INSERT into event_log 
    -> (user_id,object_id,date_event) VALUES 
    -> (7,2,'2013-05-03 08:37:11'), 
    -> (7,3,'2013-05-03 12:43:51'), 
    -> (7,2,'2013-05-03 15:33:41'), 
    -> (7,3,'2013-05-03 17:10:01'); 
Query OK, 4 rows affected (0.00 sec) 
Records: 4 Duplicates: 0 Warnings: 0 

mysql> 

下面是该查询执行

mysql> SET @given_user = 7; 
Query OK, 0 rows affected (0.00 sec) 

mysql> SET @dt = '2013-05-03'; 
Query OK, 0 rows affected (0.00 sec) 

mysql> SET @dt1 = @dt + INTERVAL 0 SECOND; 
Query OK, 0 rows affected (0.00 sec) 

mysql> SET @dt2 = @dt + INTERVAL 1 DAY; 
Query OK, 0 rows affected (0.00 sec) 

mysql> SELECT 
    ->  SEC_TO_TIME(SUM(dts)) TotalTime 
    -> FROM 
    -> (
    ->  SELECT 
    ->   (IF(object_id=2,-1,1) * 
    ->   (UNIX_TIMESTAMP(date_event) - 
    ->   UNIX_TIMESTAMP(DATE(date_event) +INTERVAL 0 SECOND))) dts 
    ->  FROM 
    ->   event_log 
    ->  WHERE 
    ->   user_id=7 AND 
    ->   object_id IN (2,3) AND 
    ->   date_event >= @dt1 AND 
    ->   date_event < @dt2 
    ->) A; 
+-----------+ 
| TotalTime | 
+-----------+ 
| 05:43:00 | 
+-----------+ 
1 row in set (0.00 sec) 

mysql> 

试试看!

+1

这里令人印象深刻的工作。 – rncrtr 2013-05-03 22:40:29