根据日期范围,如何确定每周3-5天有多少用户活动?

时间:2010-12-08 06:32:27

标签: sql mysql algorithm

假设你有一个像这样的表:

CREATE TABLE `checkins` (
  `id` bigint(20) NOT NULL default '0',
  `userid` bigint(20) default NULL,
  `timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
  PRIMARY KEY  (`id`),
  KEY `ind_userid` (`userid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8

根据日期范围,如何确定每周3-5天有多少用户活动。

这样的东西
input - two months date range
output - 310 users were active 3-5 days a week

3 个答案:

答案 0 :(得分:1)

如果您创建一个每周一行的日历表,您应该可以通过以下查询解决问题:

SELECT userid 
FROM   (SELECT userid, 
               YEARWEEK(TIMESTAMP)                  AS year_week, 
               COUNT(DISTINCT DAYOFWEEK(TIMESTAMP)) AS check_in_days 
        FROM   checkins 
        WHERE  1 = 1 -- This would be your date range filter 
        GROUP  BY userid, 
                  YEARWEEK(TIMESTAMP) 
        HAVING check_in_days BETWEEN 3 AND 5) AS user_weeks 
GROUP  BY userid 
HAVING COUNT(year_week) = (SELECT COUNT(*) 
                           FROM   year_week 
                           WHERE  1 = 1 -- This would be your date range filter 
                          ); 

(我的周表在2001年到2020年之间每周有一行。)

内部查询(user_weeks)为每个{user_id,week}返回一行,其中用户在该特定周内至少3天或最多5天签到。 (每天签到的Nr无关紧要)。外部查询为每个{user_id}返回一行,以及满足3-5天签到要求的周数。 外部选择中的having子句过滤结果,仅包括已签入多次(周)的用户作为日期范围内的实际周数。这应该照顾“连续”的周要求。

如果这有助于您,请告诉我。

修改 从功能周()更改为年周()。

答案 1 :(得分:0)

这是在oracle,但我认为它也可以在mysql中轻松完成

SELECT  year_week AS year_week,
        COUNT (year_week) AS days
FROM   (  SELECT   TO_CHAR (timestamp, 'D') AS day_of_week,
                      TO_CHAR (timestamp, 'YYYY')
                   || '-'
                   || TO_CHAR (timestamp, 'WW')
                      AS year_week
            FROM   checkins
        GROUP BY      TO_CHAR (timestamp, 'YYYY')
                   || '-'
                   || TO_CHAR (timestamp, 'WW'),
                   TO_CHAR (timestamp, 'D')
        ORDER BY   year_week)
GROUP BY  year_week order by year_week;    

TO_CHAR(timestamp, 'WW') = WEEKOFYEAR

TO_CHAR(timestamp, 'D') = DAYOFWEEK

答案 2 :(得分:0)

被视为多查询问题,其中:

  • 结果派生自第一个查询
  • secondResult 派生自第二个查询
  • minDate 是该范围内的最小日期,相当于WEEKOFYEAR(minDate)
  • maxDate 是范围内的最大日期,相当于WEEKOFYEAR(maxDate)
  • 始终保留列名 userid 时间戳

解决方案看起来像这样:

SELECT DISTINCT userid, timestamp from checkins WHERE WEEKOFYEAR(timestamp) >= minDate and WEEKOFYEAR(timestamp) <= maxDate GROUP BY userid,DAYOFWEEK(timestamp);
SELECT userid, timestamp FROM result GROUP BY userid,WEEKOFYEAR(timestamp) HAVING COUNT(timestamp) >= 3 AND COUNT(timestamp) <= 5;
SELECT COUNT(*) FROM secondResult GROUP BY userid HAVING COUNT(timestamp) = (WEEKOFYEAR(maxDate) - WEEKOFYEAR(minDate));

显然,请确保在日历包装的情况下添加52。我已经验证了这个解析,并且有理由相信可以从这个解决方案中获得正确的解决方案。