Как сгруппировать записи за определенную неделю? - PullRequest
0 голосов
/ 28 декабря 2018

Я пытаюсь собрать отчет в SQL, который будет работать в MySQL.

У меня есть таблица companies:

INSERT INTO companies
(`id`, `name`, `createdDate`)
VALUES
    (1, 'company_1', '2016-02-01 04:00:00'),
    (2, 'company_2', '2016-01-01 04:00:00'),
    (3, 'company_3', '2016-04-01 04:00:00'),
    (4, 'company_4', '2016-03-01 04:00:00'),
    (5, 'company_5', '2016-02-01 04:00:00')
;

У меня есть таблица users, где группа пользователей работает в определенной компании в одной компании для сценария для многих пользователей.Пользователи принимают приглашение присоединиться к компании, и мы фиксируем следующую дату:

INSERT INTO users
    (`userId`, `companyId`, `acceptedInviteDate`)
VALUES
    (1, 1, '2017-01-01 04:00:00'),
    (2, 1, '2017-01-02 04:00:00'),
    (3, 1, '2017-01-03 04:00:00'),
    (4, 1, '2017-01-04 04:00:00'),
    (5, 2, '2017-01-05 04:00:00'),
    (6, 2, '2017-01-09 04:00:00'),
    (7, 2, '2017-01-10 04:00:00'),
    (8, 2, '2017-01-11 04:00:00'),
    (9, 2, '2017-01-12 04:00:00'),
    (10, 3, '2017-01-13 04:00:00'),
    (11, 3, '2017-01-15 04:00:00'),
    (12, 3, '2017-01-02 04:00:00'),
    (13, 3, '2017-01-03 04:00:00'),
    (14, 3, '2017-01-04 04:00:00'),
    (15, 3, '2017-01-05 04:00:00'),
    (16, 3, '2017-01-06 04:00:00'),
    (17, 3, '2017-01-07 04:00:00'),
    (18, 3, '2017-01-08 04:00:00'),
    (19, 3, '2017-01-09 04:00:00'),
    (20, 3, '2017-01-11 04:00:00'),
    (21, 3, '2017-01-13 04:00:00'),
    (22, 3, '2017-01-15 04:00:00'),
    (23, 3, '2017-01-16 04:00:00'),
    (24, 3, '2017-01-17 04:00:00'),
    (25, 3, '2017-01-18 04:00:00'),
    (26, 3, '2017-01-19 04:00:00'),
    (27, 3, '2017-01-20 04:00:00'),
    (28, 1, '2018-01-05 04:00:00'),
    (29, 1, '2018-01-10 04:00:00'),
    (30, 1, '2018-01-15 04:00:00'),
    (31, 1, '2018-01-20 04:00:00'),
    (32, 1, '2018-01-22 04:00:00')
;

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

INSERT INTO activities
(`userId`, `activityId`, `type`, `activityDate`)
VALUES
    (1, 1, 'commit', '2018-01-01 04:00:00'),
    (1, 2, 'commit', '2018-01-02 04:00:00'),
    (1, 3, 'commit', '2018-01-03 04:00:00'),
    (1, 4, 'commit', '2018-01-04 04:00:00'),
    (1, 5, 'did', '2018-01-05 04:00:00'),
    (1, 6, 'did', '2018-01-12 04:00:00'),
    (1, 7, 'did', '2018-01-14 04:00:00'),
    (1, 8, 'did', '2018-01-29 04:00:00'),
    (1, 9, 'skipped', '2018-01-29 04:00:00'),
    (1, 10, 'did', '2018-01-29 04:00:00'),
    (1, 11, 'did', '2018-01-29 04:00:00'),
    (1, 12, 'did', '2018-01-29 04:00:00'),
    (1, 13, 'did', '2018-01-29 04:00:00'),
    (2, 14, 'commit', '2018-01-01 04:00:00'),
    (2, 15, 'did', '2018-01-02 04:00:00'),
    (2, 16, 'commit', '2018-01-03 04:00:00'),
    (2, 17, 'commit', '2018-01-04 04:00:00'),
    (2, 18, 'did', '2018-01-05 04:00:00'),
    (2, 19, 'did', '2018-01-12 04:00:00'),
    (2, 20, 'commit', '2018-01-14 04:00:00'),
    (2, 21, 'did', '2018-01-29 04:00:00'),
    (2, 22, 'skipped', '2018-01-29 04:00:00'),
    (2, 23, 'did', '2018-01-29 04:00:00'),
    (2, 24, 'did', '2018-01-29 04:00:00'),
    (2, 25, 'skipped', '2018-01-29 04:00:00'),
    (2, 26, 'did', '2018-01-29 04:00:00')

Я пытаюсь создать отчет на основе mysql, который даст мне вывод для каждой компании:

1) Количество пользователей в неделю, которые выполняли вид деятельности , выполняли в неделю, где неделя определяется как дата, начиная с даты создания компании.Не календарная неделя.Так что если компания была создана 03.03.17.Первая неделя с 03/03/17 по 03/10/17, а вторая неделя - на 7 дней позже, до недели #x, пока она не достигнет текущей даты.

2) совокупное число пользователей, для которых значение acceptInviteDate отсутствуетноль.Только те, которые приняли.Например, неделя 3 = неделя 1 + неделя 2 + неделя 3 для этой компании.

Вот пример выходных данных:

   companyId   | week# | users_with_activity_type_did | totalUsersdWhoAcceptedAnInvite
    1          | 1     | 0                            | 0
    1          | 48    | 0                            | 0
    ....
    1          | 49    | 3                            | 28
    1          | 50    | 3                            | 29
    1          | 51    | 0                            | 30

Пожалуйста, посмотрите последнюю скрипку, запущенную пользователем Sentinel --> http://sqlfiddle.com/#!9/4431be/1

Данные введены правильно, но sql неверно и возвращает неправильные данные

1 Ответ

0 голосов
/ 28 декабря 2018

Вот возможное решение с использованием предоставленных образцов данных.

Для выполнения этой работы необходима таблица измерений Weeks.Тем не менее, обратите внимание, что на основе примеров данных пользователи 1 и 2 начали работать в Company_1 до того, как была создана company_1, поэтому в таблице Weeks должны быть указаны отрицательные номера недель для сбора этих данных.

См. SQL Fiddle для полной настройки и пример кода.

Дополнительные настройки схемы MySQL 5.6 :

create table ones (num bigint);
insert into ones values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);

create table weeks as
select o.num + t.num * 10 + h.num * 100 week_no
  from ones o, ones t, ones h order by 1;
insert into weeks select -num from ones where num > 0;

drop table ones;

Запрос 1 :

select c.id companyid
     , n.week_no
     , count(distinct case when a.type = 'did' then a.userid end) users_with_activity_type_did
     , count(distinct case when a.type = 'commit' then a.userid end) users_with_activity_type_commit
     , count(distinct case when a.type = 'skipped' then a.userid end) users_with_activity_type_skip
     , count(distinct case when u.acceptedInviteDate < (c.createdDate + interval (7*(n.week_no+1)) day)
            then u.userid
       end) totalUsersWhoAcceptedAnInvite
 from companies c
cross join weeks n
 left join users u
   on u.companyid = c.id
 left join activities a
   on a.userid = u.userid
  -- and a.type = 'did'
  and (c.createdDate + interval (7*n.week_no) day) <= a.activitydate
  and a.activitydate < (c.createdDate + interval (7*(n.week_no+1)) day)
group by c.id
    , n.week_no with rollup
having max(case when u.acceptedInviteDate < (c.createdDate + interval (7*(n.week_no+1)) day)
                 and u.acceptedInviteDate >= (c.createdDate + interval (7*(n.week_no)) day)
                then 1
                when a.activityid is not null then 1
                else 0
       end) = 1

Результаты :

| companyid | week_no | users_with_activity_type_did | users_with_activity_type_commit | users_with_activity_type_skip | totalUsersWhoAcceptedAnInvite |
|-----------|---------|------------------------------|---------------------------------|-------------------------------|-------------------------------|
|         1 |      47 |                            0 |                               0 |                             0 |                             1 |
|         1 |      48 |                            0 |                               0 |                             0 |                             4 |
|         1 |     100 |                            2 |                               2 |                             0 |                             5 |
|         1 |     101 |                            2 |                               1 |                             0 |                             6 |
|         1 |     102 |                            0 |                               0 |                             0 |                             8 |
|         1 |     103 |                            0 |                               0 |                             0 |                             9 |
|         1 |     104 |                            2 |                               0 |                             2 |                             9 |
|         1 |  (null) |                            2 |                               2 |                             2 |                             9 |
|         2 |      52 |                            0 |                               0 |                             0 |                             1 |
|         2 |      53 |                            0 |                               0 |                             0 |                             5 |
|         2 |  (null) |                            0 |                               0 |                             0 |                             5 |
|         3 |      39 |                            0 |                               0 |                             0 |                             4 |
|         3 |      40 |                            0 |                               0 |                             0 |                             9 |
|         3 |      41 |                            0 |                               0 |                             0 |                            17 |
|         3 |      42 |                            0 |                               0 |                             0 |                            18 |
|         3 |  (null) |                            0 |                               0 |                             0 |                            18 |
|    (null) |  (null) |                            2 |                               2 |                             2 |                            32 |

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

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

Последнее изменение - добавление предложения with rollup к предложению group by для получения общих итогов.

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