У меня есть вопрос, связанный с SQL, с которым я хотел бы получить некоторую помощь, поскольку подходящий ответ ускользал от меня в течение некоторого времени.
Справочная информация
Я работаю с продуктом поставщика, который имеет базу данных Oracle, которая служит в качестве бэкэнда.У меня есть возможность написать любой специальный SQL для запроса базовых таблиц, но я не могу вносить какие-либо изменения в их базовую структуру (или в саму модель данных).Интересующая меня таблица в настоящее время имеет около + 1 млн строк и, по сути, отслеживает сеансы пользователей.Он имеет 4 интересующих столбца: session_id
(который является первичным ключом и уникальным для сеанса), user_name
, start_date
(дата, которая отслеживает начало сеанса) и stop_date
(дата, которая отслеживает конецсессии).Моя цель - выполнить агрегацию данных для активных сеансов по месяцам, дням и часам с заданной датой начала и окончания.Мне нужно создать представление (или 3 отдельных представления), которые могут либо выполнять само агрегацию, либо служить промежуточным объектом, из которого я могу затем запрашивать и выполнять агрегацию.Я понимаю, что возможное представление SQL / view может фактически нуждаться в трех разных представлениях (одно для месяца, одно для дня, одно для часа), но мне кажется, что концепция (после достижения) должна быть одинаковой независимо от периода времени.
Пример текущей таблицы
Имя таблицы = web_session
| Session_id | user_name | start_date | stop_date
----------------------------------------------------------------------------
| 1 | joe | 4/20/2017 10:42:10 PM | 4/21/2017 2:42:10 AM |
| 2 | matt | 4/20/2017 5:43:10 PM | 4/20/2017 5:59:10 PM |
| 3 | matt | 4/20/2017 3:42:10 PM | 4/20/2017 5:42:10 PM |
| 4 | joe | 4/20/2017 11:20:10 AM | 4/20/2017 4:42:10 PM |
| 5 | john | 4/20/2017 8:42:10 AM | 4/20/2017 11:42:10 AM |
| 6 | matt | 4/20/2017 7:42:10 AM | 4/20/2017 11:42:10 PM |
| 7 | joe | 4/19/2017 11:20:10 PM | 4/20/2017 1:42:10 AM |
Идеальный вывод для часового просмотра
-12: 00 может быть 0 или 24 для примера
| Date | HR | active_sessions | distinct_users |
------------------------------------------------------------
| 4/21/2017 | 2 | 1 | 1 |
| 4/21/2017 | 1 | 1 | 1 |
| 4/20/2017 | 0 | 1 | 1 |
| 4/20/2017 | 23 | 1 | 1 |
| 4/20/2017 | 22 | 1 | 1 |
| 4/20/2017 | 17 | 2 | 1 |
| 4/20/2017 | 16 | 2 | 2 |
| 4/20/2017 | 15 | 2 | 2 |
| 4/20/2017 | 14 | 1 | 1 |
| 4/20/2017 | 13 | 1 | 1 |
| 4/20/2017 | 12 | 1 | 1 |
| 4/20/2017 | 11 | 3 | 3 |
| 4/20/2017 | 10 | 2 | 2 |
| 4/20/2017 | 9 | 2 | 2 |
| 4/20/2017 | 8 | 2 | 2 |
| 4/20/2017 | 7 | 1 | 1 |
| 4/20/2017 | 1 | 1 | 1 |
| 4/20/2017 | 0 | 1 | 1 |
| 4/19/2017 | 23 | 1 | 1 |
Конечная цель и другие параметры
Что яв конечном итоге попытаться добиться этого вывода - заполнить линейную диаграмму, которая отображает количество активных сеансов за месяц, день или час (используется в выходных данных примера) между двумя датами.В примере с часом дата в сочетании с часами будет использоваться вдоль оси X, а активные сеансы будут использоваться вдоль оси Y.Отличное количество пользователей будет доступно, если пользователь завис над точкой на графике.К сведению Активные сеансы - это общее количество сеансов, открытых в любой точке в течение интервала.Отдельные пользователи - это общее количество отдельных пользователей за интервал.Если бы я входил и выходил дважды в течение одного часа, это были бы 2 активных сеанса, но только 1 отдельный пользователь.
Альтернативные решения
Похоже, что это проблема, которая, возможно, возникала уже много раз, но из всех моих исследований по поиску и переполнению стека я не могу найтиправильный подход.Если я неправильно думаю о запросе или идеальном выводе, я ОТКРЫТ ДЛЯ ИЗМЕНЕНИЯ ПРЕДЛОЖЕНИЙ, которые позволяют мне получить желаемый вывод для надлежащего заполнения диаграммы на внешнем интерфейсе.
Некоторые SQL, которые я пробовал (Доброе вера)
Я пробовал много запросов, но я начну с этого, так как он самый близкий, но он очень медленный (необычно), и все равно нет.выдай нужный мне результат.
Select * FROM (
SELECT
u.YearDt, u.MonthDt, u.DayDt, u.HourDt, u.MinDt,
COUNT(Distinct u.session_id) as unique_sessions,
COUNT(Distinct u.user_name) as unique_users,
LISTAGG(u.user_name, ', ') WITHIN GROUP (ORDER BY u.user_name ASC) as users
FROM
(SELECT EXTRACT(year FROM l.start_date) as YearDt,
EXTRACT(month FROM l.start_date) as MonthDt,
EXTRACT(day FROM l.start_date) as DayDt,
EXTRACT(HOUR FROM CAST(l.start_date AS TIMESTAMP)) as HourDt,
EXTRACT(MINUTE FROM CAST(l.start_date AS TIMESTAMP)) as MinDt,
l.session_id,
l.user_name,
l.start_date as act_date,
1 as is_start
FROM web_session l
UNION ALL
SELECT EXTRACT(year FROM l.stop_date) as YearDt,
EXTRACT(month FROM l.stop_date) as MonthDt,
EXTRACT(day FROM l.stop_date) as DayDt,
EXTRACT(HOUR FROM CAST(l.stop_date AS TIMESTAMP)) as HourDt,
EXTRACT(MINUTE FROM CAST(l.stop_date AS TIMESTAMP)) as MinDt,
l.session_id,
l.user_name,
l.stop_date as act_date,
0 as is_start
FROM web_session l
) u
GROUP BY CUBE ( u.YearDt, u.MonthDt, u.DayDt, u.HourDt, u.MinDt)
) c