Я пытаюсь написать SQL-запрос, чтобы сгенерировать итоговую строку для действий, выполняемых данным пользователем за указанный период. У меня есть следующая соответствующая структура таблицы:
пользователи
audit_periods (может быть обработка, доставка, перерыв и т. Д.)
- user_id
- period_type (может быть «обработка», «доставка» и т. Д. - в настоящее время не нормализовано)
- started_at
- finish_at (может быть нулевым для текущего периода, следовательно, логика примерно раз ниже)
audit_tasks
- audit_period_id
- audit_task_type_id
- created_at
- счет
audit_task_types
- name ("scan", "place_in_pallet" и т. Д.)
- оценка (кажется излишней, но нам нужно сохранить оценку, полученную на Audit_task во время выполнения, так как оценка Audit_task_type может измениться позже)

Для каждого пользователя за данный период я хотел бы создать что-то вроде следующего ряда данных:
users.id users.email time_spent_processing time_spent_shipping ... number_of_scans number_of_pallets
, который будет рассчитан для каждого пользователя:
- Какие audit_periods хотя бы частично попадают в нужное окно? (Использует start_at и finish_at.)
- Сколько времени пользователь провел в каждом типе audit_period? (Я хотел бы представить группу по параметру audit_periods.period_type.)
- Какие Audit_tasks попадают в желаемое окно? (Использует созданный_кат - пока нет в коде ниже.)
- Сколько из каждого типа audit_task пользователь выполнил во время окна? (Присоединяется к Audit_task_type и, вероятно, включает группу по Audit_task_types.name.)
- Сколько очков было заработано за период времени? (Суммирует оценки всех заданий audit_t в окне.)
Я исчерпал все известные мне уловки SQL (не так много) и придумал что-то вроде следующего:
select
u.id as user_id,
u.email as email,
u.team as team,
ap.period_type as period_type,
att.name,
time_to_sec(
timediff(least("2011-03-17 00:00:00", ifnull(ap.finished_at, utc_timestamp())), greatest("2011-03-16 00:00:00", ap.started_at))
) as period_duration,
sum(at.score) as period_score
from audit_periods as ap
inner join users as u on ap.user_id = u.id
left join audit_tasks as at on at.audit_period_id = ap.id
left join audit_task_types as att on at.audit_task_type_id = att.id
where (ap.started_at >= "2011-03-16 00:00:00" or (ap.finished_at >= "2011-03-17 00:00:00" and ap.finished_at <= "2011-03-17 00:00:00"))
and (ap.finished_at <= "2011-03-17 00:00:00" or (ap.started_at >= "2011-03-16 00:00:00" and ap.started_at <= "2011-03-16 00:00:00"))
and u.team in ("Foo", "Bar")
group by u.id, ap.id, at.id
но это, по-видимому, функционально эквивалентно простому выбору всех задач аудита в конце. Я пробовал также несколько подзапросов, но безрезультатно. Более непосредственно, это генерирует что-то вроде (пропуская менее важные столбцы):
user_id | period_type | period_duration | name | score
1 processing 1800s scan 200
1 shipping 1000s place_in_pallet 100
1 shipping 1000s place_in_pallet 100
1 break 500s null null
когда я хочу:
user_id | processing | shipping | break | scan | place_in_pallet | score
1 1800s 1000s 500s 1 2 400
Я могу легко получить все Audit_tasks для данного пользователя и свернуть их в коде, но я могу получить сотни тысяч Audit_tasks за определенный период, поэтому это нужно сделать в SQL.
Просто чтобы прояснить ситуацию - я ищу запрос для генерации одной строки на пользователя, содержащей сводные данные, собранные по трем остальным таблицам. Итак, для каждого пользователя я хочу знать, сколько времени он провел в каждом из типов Audit_period (обработка 3600 секунд, доставка 3200 секунд и т. Д.), А также, сколько из каждого выполненного им задания Audit_task (5 сканирований, 10 размещенных в поддон и т. д.).
Я думаю, что у меня есть элементы решения, у меня просто проблемы с их объединением. Я точно знаю, как это сделать в Ruby / Java / и т. Д., Но я не думаю, что достаточно хорошо понимаю SQL, чтобы понять, какой инструмент мне не хватает. Нужна ли временная таблица? Союз? Какая-то другая конструкция целиком?
Любая помощь очень ценится, и я могу уточнить, является ли все это полным вздором.