如果您要在 MySQL 中执行此操作,则需要自连接。因为 MySQL 没有内置的 rownum 函数,所以进行自连接是一件很痛苦的事情。但这仍然是可行的。
首先,我们需要创建一个子查询来创建一个虚拟表来模拟SELECT rownum, user, timestamp FROM login
我们可以这样做。http://sqlfiddle.com/#!2/bf6ef/2/0
SELECT @a:=@a+1 AS rownum, user, timestamp
FROM (
SELECT user, timestamp
FROM login
ORDER BY timestamp
) C,
(SELECT @a:=0) s
接下来,我们需要将此虚拟表自连接到其自身的副本。在这个结果集中,我们想要的是表中所有连续行对的列表。该查询是一个毛球——它将结构化查询语言放入结构化查询中。但它有效。这是: http ://sqlfiddle.com/#!2/bf6ef/4/0
SELECT first.user AS fuser,
first.timestamp AS ftimestamp,
second.user AS suser,
second.timestamp as stimestamp,
TIMESTAMPDIFF(SECOND, first.timestamp, second.timestamp) AS timeloggedin
FROM (
SELECT @a:=@a+1 AS rownum, user, timestamp
FROM (
SELECT user, timestamp
FROM login
ORDER BY timestamp
) C,
(SELECT @a:=0) s
) AS first
JOIN (
SELECT @b:=@b+1 AS rownum, user, timestamp
FROM (
SELECT user, timestamp
FROM login
ORDER BY timestamp
) C,
(SELECT @b:=0) s
) AS second ON first.rownum+1 = second.rownum
比较连续行的整个技巧是
SELECT (virtual_table) AS first
JOIN (virtual_table) AS second ON first.rownum+1 = second.rownum
查询模式。rownum+1 = rownum 将具有连续行号的行聚集在一起。
接下来,我们需要汇总该查询的结果以获取每个用户的总登录时间。这将像这样工作:
SELECT user, SUM(timeloggedin) AS timeloggedin
FROM (
/* the self-joined query */
) AS selfjoin
GROUP BY user
ORDER BY user
看起来像这样: http ://sqlfiddle.com/#!2/bf6ef/5/0
这是放在一起的整个查询。
SELECT user, SUM(timeloggedin) AS timeloggedin
FROM (
SELECT first.user AS user,
TIMESTAMPDIFF(SECOND, first.timestamp, second.timestamp) AS timeloggedin
FROM (
SELECT @a:=@a+1 AS rownum, user, timestamp
FROM (
SELECT user, timestamp
FROM login
ORDER BY timestamp
) C,
(SELECT @a:=0) s
) AS first
JOIN (
SELECT @b:=@b+1 AS rownum, user, timestamp
FROM (
SELECT user, timestamp
FROM login
ORDER BY timestamp
) C,
(SELECT @b:=0) s
) AS second ON first.rownum+1 = second.rownum
) AS selfjoin
GROUP BY user
ORDER BY user
对于习惯于程序、算法和思维的人来说,这并不是真正的直观。但这是在 SQL 中进行这种连续行比较的方式。