2012-01-18 41 views
3

我需要回答这样一个问题中计算出的任意N型秒持续的SQL MAX():如何在一定的时间内

对于每个用户,什么是大部分项目那用户在START_TIMESTAMPEND_TIMESTAMP之间的任何60秒 时间范围内查看?

60秒的时间范围是一个滑动窗口。这不仅仅是每个整个分钟的“物品查看次数”问题。另外,60秒只是一个例子,它应该可以在任何秒数内工作。

我的数据存储这样的:

-- Timestamped log of users viewing items 
CREATE TABLE user_item_views (
    user_id integer, 
    item_id integer, 
    timestamp timestamp 
); 

做它的每个整分钟是很容易的,只是格式时间戳像YYYY-MM-DD hh:mm做由格式化的日期和时间以及USER_ID分组计数。

这样做的滑动窗口,我不知道如何处理。

如果这在SQL以外更容易,我很乐意将数据导出到另一种格式或使用其他语言。

所需的输出是一样的东西:

User ID Max items viewed in N seconds, between START and END. 
...  ... 
...  ... 
...  ... 

我怎样才能做到这一点?

+0

什么DBMS是什么? MSSQL Oracle MySQL? – JoshBerke 2012-01-18 16:31:55

+0

@JoshBerke我可以使用任何开放源代码并且最好易于访问。如果另一种工具更适合,它不一定是RDBMS。对于RDBMS,按照最优选到最不优选的顺序:sqlite3,PostgreSQL或MySQL。 – Rebe 2012-01-18 16:35:58

+0

@Rebe我真的很感激某种反馈,无论我的想法是否奏效。另外,我很乐意看到您最终使用的代码! – Tomalak 2012-01-18 18:56:01

回答

2

下面是我该怎么做(小心,未经测试的代码,这只是概述这个想法)。

您需要一个辅助表,其行数应等于START_TIMESTAMPEND_TIMESTAMP之间的秒数。在开始查询之前将其创建为临时表。我们称之为every_second。我假设你的最低时间分辨率是一秒钟。

然后做:

SELECT 
    s.timestamp, 
    v.user_id, 
    (
    SELECT COUNT(*) FROM user_item_views 
    WHERE timestamp BETWEEN s.timestamp AND ADDTIME(s.timestamp, '00:00:59') 
      AND user_id = v.user_id 
) item_count 
FROM 
    every_second s 
    LEFT JOIN user_item_views v ON v.timestamp = s.timestamp 
GROUP BY 
    s.timestamp, 
    v.user_id 

存储在另一个临时表,并从中选择所需的最大值(这是因为“选择组最高”的问题需要)。

+0

看起来不错让我试一试 – Rebe 2012-01-18 16:52:10

+0

@Rebe:我不保证。告诉我它是怎么回事。 – Tomalak 2012-01-18 16:58:33

0

在MySQL(假设timestamp是唯一的):

SELECT 
     user_id 
    , MAX(max_count) AS max_count 
FROM 
    (SELECT 
      a.user_id 
     , COUNT(*)  AS max_count 
    FROM 
      user_item_views AS a 
     JOIN 
      user_item_views AS b 
     ON a.user_id = b.user_id 
     AND a.timestamp <= b.timestamp 
     AND b.timestamp < a.timestamp + INTERVAL 60 SECOND 
    GROUP BY 
      a.user_id 
     , a.timestamp 
) AS grp 
GROUP BY 
     user_id 
相关问题