Связать 2 записи о входе и входе без id сессии
Всем привет. Столкнулся с проблемой компиляции данных для отчетика. Отчет прост как 2 пальца. Нужно вывести данные о пользователях и их сессиях. Когда воши и когда вышли. Ну и там другие данные, но это не предмет вопроса.
Сложность в том, что каждая запись в БД это либо время входа в систему или время выхода в систему, что логично. Но у этих записей нет ID сессии, по которому можно было бы связать вход и выход между собой. У записей из ощего только имя пользователя и имя ПК.
Как можно связать 2 записи о входе и выходе в одну ?
Примерно вот так выглядит мой текущий код. Там еще тянутся данные из другой таблицы, но это значения не играет.
public async Task<PageData<AgentsWorkingTimeReportData>> GetAgentsWorkingTimeReportAsync(DateTime PeriodFrom, DateTime PeriodTo, List<string> userLogins, int CurrentPage, int PageSize)
{
string queryLoginLogout = @"
SELECT
ap_agentid AS AgentId,
linenumber AS Number,
login_dt AS LoginDt,
logout_dt AS LogoutDt
FROM
agent_login_logout_stat
WHERE
(login_dt BETWEEN @PeriodFrom AND @PeriodTo)
OR
(logout_dt BETWEEN @PeriodFrom AND @PeriodTo)
AND (@UserLogins IS NULL OR ap_agentid = ANY(@UserLogins))
ORDER BY
ap_agentid, login_dt, logout_dt
LIMIT @PageSize OFFSET @Offset";
// Запрос из таблицы agentstatusevents_integrated
string queryAgentStatus = @"
SELECT
ap_agentid AS AgentId,
cti_workplaceid AS WorkplaceID,
dt_add AS AddDate
FROM
agentstatusevents_integrated
WHERE
ap_agentid = ANY(@UserLogins)
AND dt_add BETWEEN @PeriodFrom AND @PeriodTo";
var parameters = new
{
PeriodFrom,
PeriodTo,
UserLogins = userLogins?.ToArray(),
PageSize,
Offset = (CurrentPage - 1) * PageSize
};
using var dbConnection = new NpgsqlConnection(dbConnectionString);
// Выполнение запросов
var loginLogoutData = (await dbConnection.QueryAsync<AgentsWorkingTimeReportDataМ>(queryLoginLogout, parameters)).ToList();
var agentStatusData = (await dbConnection.QueryAsync<AgentStatusData>(queryAgentStatus, parameters)).ToList();
var totalCountQuery = @"
SELECT COUNT(*)
FROM agent_login_logout_stat
WHERE (login_dt BETWEEN @PeriodFrom AND @PeriodTo)
OR (logout_dt BETWEEN @PeriodFrom AND @PeriodTo)
AND (@UserLogins IS NULL OR ap_agentid = ANY(@UserLogins))";
var totalCount = await dbConnection.ExecuteScalarAsync<int>(totalCountQuery, parameters);
// Объединение данных
var agentStatusMap = agentStatusData
.GroupBy(a => a.AgentId)
.ToDictionary(g => g.Key, g => g.First().WorkplaceID);
var responseItems = loginLogoutData.Select(item => new AgentsWorkingTimeReportData
{
AgentId = item.AgentId,
AgentName = userLogins.Contains(item.AgentId) ? item.AgentId : string.Empty,
Number = item.Number,
WorkplaceID = agentStatusMap.ContainsKey(item.AgentId) ? agentStatusMap[item.AgentId] : string.Empty,
LoginDt = item.LoginDt.HasValue ? item.LoginDt.Value.ToString("yyyy-MM-dd HH:mm:ss") : string.Empty,
LogoutDt = item.LogoutDt.HasValue ? item.LogoutDt.Value.ToString("yyyy-MM-dd HH:mm:ss") : string.Empty
}).ToList();
return new PageData<AgentsWorkingTimeReportData>
{
Items = responseItems,
TotalCount = totalCount,
PageNumber = CurrentPage
};
}
public class AgentStatusData
{
public string AgentId { get; set; }
public string WorkplaceID { get; set; }
public DateTime AddDate { get; set; }
}
public class AgentsWorkingTimeReportDataМ
{
public string AgentId { get; set; }
public string Number { get; set; }
public DateTime? LoginDt { get; set; }
public DateTime? LogoutDt { get; set; }
}
public struct AgentsWorkingTimeReportData
{
// ID агента
public string AgentId { get; set; }
// Имя агента
public string AgentName { get; set; }
// Внутренний номер
public string Number { get; set; }
// Рабочее место
public string WorkplaceID { get; set; }
// Вход в систему
public string LoginDt { get; set; }
// Выход из системы
public string LogoutDt { get; set; }
}