连续几小时获取sql

时间:2016-11-02 08:31:33

标签: php mysql sql

我有一个问题。假设我在SQL中有这个表:

date                        user_id             
2015-03-17 00:06:12         143
2015-03-17 01:06:12         143
2015-03-17 02:06:12         143
2015-03-17 09:06:12         143
2015-03-17 10:10:10         200

我想获得连续数小时。例如,对于用户143,我希望获得2小时,对于用户200 0小时。我试过这样:

select user_id, TIMESTAMPDIFF(HOUR,min(date), max(date)) as hours
from myTable
group by user_id

但是此查询会提取所有非连续小时数。是否可以通过查询解决问题,还是需要在PHP中对结果进行后处理?

2 个答案:

答案 0 :(得分:2)

使用变量与上一行进行比较。

SELECT user_id, SUM(cont_hour) FROM (
    SELECT
    user_id,
    IF(CONCAT(DATE(@prev_date), ' ', HOUR(@prev_date), ':00:00') - INTERVAL 1 HOUR = CONCAT(DATE(t.date), ' ', HOUR(t.date), ':00:00')
AND @prev_user = t.user_id, 1, 0) AS cont_hour
    , @prev_date := t.date
    , @prev_user := t.user_id
    FROM
    table t
    , (SELECT @prev_date := NULL, @prev_user := NULL) var_init_subquery
    WHERE t.date BETWEEN <this> AND <that>
    ORDER BY t.date
) sq
GROUP BY user_id;

我的比较比你想象的要复杂得多,但我认为有必要,你不要只是比较小时,而且,它是同一天(或前一天,当它在午夜左右)。

  • 您可以阅读有关用户变量here
  • 的更多信息

作为一个简短的解释:ORDER BY非常重要,以及SELECT子句中的顺序。 @prev_date保存&#34;前一行&#34;,因为我们在进行比较后分配了当前行的值。

答案 1 :(得分:1)

使用临时变量的另一个版本:

SET @u := 0;
SET @pt := 0;
SET @s := 0;

SELECT `user_id`, MAX(`s`) `conseq` FROM
(
  SELECT
  @s := IF(@u = `user_id`,
    IF(UNIX_TIMESTAMP(`date`) - @pt = 3600, @s + 1, @s),
      0) s,
  @u := `user_id` `user_id`,
  @pt := UNIX_TIMESTAMP(`date`) pt
  FROM `users`
  ORDER BY `date`
) AS t
GROUP BY `user_id`

子查询按日期对行进行排序,然后将user_id与之前的值进行比较。如果用户ID相等,则计算date与上一个时间戳@pt之间的差异。如果差异是一小时(3600秒),则@s计数器将增加1。否则,计数器重置为0:

s user_id pt
0 143     1426529172
1 143     1426532772
2 143     1426536372
2 143     1426561572
0 200     1426565410

外部查询收集每user_id的最大计数器值,因为最大计数器值对应于每user_id的最后一个计数器值。

输出

user_id conseq
143     2
200     0     

注意,查询接受恰好1小时的差异。如果您想要更灵活的条件,只需调整比较即可。例如,您可以接受3000到4000秒之间的间隔差异,如下所示:

  @s := IF(@u = `user_id`,
    IF( (UNIX_TIMESTAMP(`date`) - @pt) BETWEEN 3000 AND 4000, @s + 1, @s),
      0) s