Структура базы данных для хранения статистики по дням, неделям, месяцам, годам - PullRequest
11 голосов
/ 04 марта 2009

Я должен собирать статистику по дням, неделям, месяцам и годам активности пользователя на сайте. Я на этапе проектирования БД, и я хотел сделать этот этап правильно, так как это облегчит мою жизнь кодирования.

Что мне нужно сделать, так это просто увеличивать значения в полях на 1 в БД каждый раз, когда происходит какое-либо действие. Тогда я могу подтянуть дату по каждому дню, каждой неделе, каждому месяцу и году. Как должна быть структурирована моя БД? Извинения, если это простой вопрос для большинства. Также было бы здорово, если бы эта структура была расширяемой, чтобы ее можно было разбить на другие категории.

Сложность, с которой я столкнулся, состоит в том, что каждый месяц состоит из большего числа дней, и эти дни меняют каждый календарный год.

Спасибо всем за любую помощь или направление.

Другая информация: Linux Machine, использующая PHP и MySQL

Ответы [ 7 ]

19 голосов
/ 04 марта 2009

Вместо обновления счетчиков за день, неделю и т. Д. Просто вставляйте строку в таблицу каждый раз, когда происходит следующее действие:

insert into activities (activity_date, activity_info) 
values (CURRENT_TIMESTAMP, 'whatever');

Теперь ваши отчеты очень просты:

select count(*) from activities
where activity_date between '2008-01-01' and '2008-01-07';

или

select YEARWEEK(`activity_date`) as theweek, count(*)
group by theweek
3 голосов
/ 04 марта 2009
  1. таблица событий: идентификатор, идентификатор активности, дата и время, идентификатор пользователя.
  2. таблица пользователей: идентификатор, имя пользователя и т. Д.
  3. таблица действий: идентификатор, название деятельности и т. Д.

Просто введите новую строку в события, когда событие происходит. Затем вы можете анализировать события, но манипулировать временем, датой, пользователем, активностью и т. Д.

3 голосов
/ 04 марта 2009

Вы можете просто добавить записи в таблицу и SELECT их, используя агрегатные функции.

Если по какой-то причине вам необходимо вести сводную статистику, вы можете использовать:

CREATE TABLE aggregates (type VARCHAR(20), part VARCHAR(10) NOT NULL PRIMARY KEY, activity INT)

INSERT INTO aggregates (type, part, activity)
VALUES ('year', SUBSTRING(SYSDATE(), 1, 4), 1)
ON DUPLICATE KEY UPDATE activity = activity + 1

INSERT INTO aggregates (type, part, activity)
VALUES ('month', SUBSTRING(SYSDATE(), 1, 7), 1)
ON DUPLICATE KEY UPDATE activity = activity + 1

INSERT INTO aggregates (type, part, activity)
VALUES ('day', SUBSTRING(SYSDATE(), 1, 10), 1)
ON DUPLICATE KEY UPDATE activity = activity + 1

Это автоматически обновит существующие строки и вставит несуществующие при необходимости.

2 голосов
/ 04 марта 2009

Для начала вы, вероятно, представили бы одну таблицу, так как это была бы наиболее нормализованная форма. В таблице будет просто запись для каждого полученного вами попадания, в каждой строке будет указана дата / время этого попадания.

Теперь, таким образом, чтобы получить статистику за каждый час, день, неделю и т. Д., Запросы просты, но вашей базе данных придется выполнить довольно тяжелую работу с запросами. В частности, запросы, в которых используются суммы, числа или средние значения, должны извлекать все соответствующие строки.

Вы можете обойти это, предварительно рассчитав требуемые значения во второй таблице и убедившись, что регулярно синхронизируете эту таблицу с первой. Проблема в том, что вы сами будете нести ответственность за синхронизацию этого кэша.

Это, вероятно, будет включать в себя создание строки для каждого часа. По-прежнему будет намного быстрее выполнять запрос в течение дня или месяца, если вы выбираете не более 24 строк в день.

Ваше другое предложение состояло в том, чтобы собрать его с самого начала, никогда не сохраняя каждый удар в виде строки. Вы, вероятно, сделаете это, как и раньше, с строкой за каждый час. Каждое попадание будет увеличивать соответствующий ряд часов на один. Вы будете иметь данные только в одном месте, и они уже будут довольно хорошо обобщены.

Причина, которую я предлагаю по часам, а не по дням, заключается в том, что это все еще дает вам возможность поддерживать несколько часовых поясов. Если ваша гранулярность относится только к дню, у вас нет такой возможности.

1 голос
/ 04 марта 2009

Использовать схему в виде звезды. (или, возможно, дизайн снежинки).

Схема в виде звезды

В итоге вы будете вставлять в таблицу фактов каждое новое действие. Смотрите предложение Тони.

Вам потребуются как минимум две таблицы измерений, одна для пользователей и одна для временных рамок. Вероятно, будут размеры для вида деятельности, и, возможно, даже для местоположения. Это зависит от того, что вы хотите сделать с данными.

Ваш вопрос относится к таблице измерений временных рамок. Давайте назовем это «Альманах». Выберите гранулярность. Давайте скажем день. Альманах будет иметь один ряд в день. Первичным ключом может быть дата. Ваша таблица фактов должна включать этот первичный ключ в качестве внешнего ключа, чтобы облегчить объединение. (Не имеет значения, объявляете ли вы его как внешний ключ. Это влияет только на ссылочную целостность во время процесса обновления.)

Включите столбцы в Альманах для каждого отчетного периода, о котором вы можете подумать. Неделя, месяц, квартал, год и т. Д. Вы можете даже включать отчетные периоды, которые относятся к собственному календарю вашей компании.

Вот статья, сравнивающая ER и DM. Я необычен тем, что мне нравятся оба метода, выбирая подходящий метод для соответствующей задачи.

http://www.dbmsmag.com/9510d05.html

1 голос
/ 04 марта 2009

Ответ Тони Эндрюса является самым простым, однако в приложениях хранилища данных иногда используется структура снежинки: таблица, в которой подсчитываются все операции, другая для операций в день, другая для операций в месяц и третья для операций в год. , С такой структурой активность между любыми двумя датами может быть вычислена очень эффективно. https://en.wikipedia.org/wiki/Snowflake_schema

0 голосов
/ 02 декабря 2013

Ваш вопрос относится к таблице измерений временных рамок. Давайте назовем это «Альманах». Выберите гранулярность. Давайте скажем день. Альманах будет иметь один ряд в день. Первичным ключом может быть дата. Ваша таблица фактов должна включать этот первичный ключ в качестве внешнего ключа, чтобы облегчить объединение. (Не имеет значения, объявляете ли вы его как внешний ключ. Это влияет только на ссылочную целостность во время процесса обновления.)

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