Самостоятельное присоединение к таблице с сохранением порядка строк

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

id
time
app
user
server
type (can be IN or OUT)

Таким образом, пользователь начинает использовать определенное приложение, и когда он получает право на использование приложения, в журнал заносится строка, а для столбца типа устанавливается значение «OUT».

Точно так же, когда они перестают использовать приложение, регистрируется еще одна строка, и теперь для столбца типа устанавливается значение «IN».

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

Итак, я сделал следующий запрос, выполняя самосоединение таблицы

SELECT A.time as OutTime, B.time as InTime, A.app, 
A.username, A.requestserver
FROM logs A, logs B
WHERE A.app = B.app
AND A.username = B.username
AND A.requestserver = B.requestserver
AND A.type = 'OUT'
AND B.type = 'IN'
AND A.time < B.time

Я не уверен, что логика этого на 100% верна. Что, если есть случай, когда один и тот же пользователь с одного сервера имеет, например, два сеанса:

ВЫХОД (1) -> 10:00

В (1) -> 13:00

ВЫХОД (2) -> 15:00

ВХОД (2) -> 19:00

Теперь с моей логикой есть шанс, что я могу просто создать сеанс с 10:00 до 19:00, что неверно. Как бы я поступил по этому поводу?

Какой order? ORDER нет! Кстати: вместо этого вы можете (должны!) использовать оператор соединения.

wildplasser 05.05.2022 00:42

@wildplasser я имею в виду порядок добавления строк в таблицу

Serda Shehu 05.05.2022 11:13
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
0
2
44
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

Предполагая, что ваше поле time представляет собой полную временную метку, а не только время суток:

with sessionized as (

select
    *,
    last_value(
        case when type = 'IN' then time end
        ignore nulls
    ) over (
        partition by username, app, requestserver
        order by time asc
        rows between unbounded preceding and current row
    ) as session_start

from logs

)
select *
from sessionized 
where type = 'OUT'

Другие вопросы по теме