Основываясь на диапазоне дат, как я могу узнать, сколько пользователей было активным 3-5 дней в неделю? - PullRequest
2 голосов
/ 08 декабря 2010

Предположим, у вас есть таблица типа:

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 ]

1 голос
/ 08 декабря 2010

Если вы создадите таблицу календаря с одной строкой для каждой недели, вы сможете решить свою проблему с помощью запроса, подобного следующему:

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 дней в этой конкретной неделе.(Количество проверок за один день не имеет значения).Внешний запрос возвращает одну строку для каждого {user_id} вместе с количеством недель, которые удовлетворяют установленному требованию 3-5 дней.Условие «Наличие» во внешнем фильтре выбора включает результаты только тех пользователей, которые зарегистрировались столько раз (недель), сколько и фактических недель в вашем диапазоне дат.Это должно учитывать требование «последовательных» недель.

Дайте мне знать, поможет ли это вам.

Редактировать Изменено с функции week () на yearweek ().

0 голосов
/ 08 декабря 2010

Рассматривается как проблема с несколькими запросами, где:

  • результат выводится из первого запроса
  • secondResult выводится из второго запроса
  • minDate - минимальная дата в диапазоне, эквивалентная WEEKOFYEAR(minDate)
  • maxDate - максимальная дата в диапазоне, заданная как эквивалентная WEEKOFYEAR(maxDate)
  • Имена столбцов ИД пользователя и отметка времени всегда сохраняются

Решение будет выглядеть примерно так:

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 в случаях, когда календарь переворачивается. Я проверил этот анализ и чувствую себя достаточно уверенным в том, что из этого можно получить правильное решение.

0 голосов
/ 08 декабря 2010

Это в оракуле, но я думаю, что это легко сделать и в 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...