MySQL рассчитать время онлайн - PullRequest
2 голосов
/ 10 октября 2010

Можно ли рассчитать время в сети из таблицы, например,

logtype   time  
----------------
login     2:30  
logout    2:45  
login     3:20  
logout    4:50  
login     5:00  
login     5:10  
logout    6:00  

Это может привести к дополнительным входам в систему, потому что иногда сервер падает и не добавляет выход из системы.Можете ли вы сделать что-то подобное только в MySQL или вам придется использовать, возможно, ColdFusion?И если да, то как бы вы сделали это в MySQL / ColdFusion?

Все, что я хочу - это грубое общее время в сети, часы, дни, минуты и т. Д. Для конкретного пользователя.

Ответы [ 3 ]

1 голос
/ 10 октября 2010

(см. Мои заметки выше, пожалуйста.)

Для данных, которые у вас будут, однако, путем объединения последовательных пар входа в систему / выхода из системы, вы можете обработать данные, чтобы получить необходимую информацию простоиспользуя простую функцию dateDiff ([datepart], [date 1], [date 2]) в CF, чтобы выяснить разницу, если вы уже запросили данные.

Для обработки данных я бы предложил добавить еще одну строку в вашу таблицу - ту, которая обрабатывает идентификатор сеанса.Это обеспечит правильное сопряжение вашего времени входа / выхода.Затем вы можете настроить свои запросы примерно так:

<cfquery name="getSession" datasource="[dsn]">
   SELECT DISTINCT sessionID
   FROM logTable
   WHERE userID = <cfqueryparam cfsqltype="cf_sql_integer" value="[inputted userID]" />
</cfquery>

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

<cfoutput query="getSessions">
   <cfquery name="getSessionInfo" datasource="[dsn]">
      SELECT 
      (SELECT time 
         FROM logTable 
         WHERE sessionID = <cfqueryparam cfsqltype="cf_sql_varchar" value="#getSessions.sessionID# />
         AND logType = <cfqueryparam cfsqltype="cf_sql_varchar" value="login" />)
      AS loginTime,
      (SELECT time 
         FROM logTable 
         WHERE sessionID = <cfqueryparam cfsqltype="cf_sql_varchar" value="#getSessions.sessionID# />
         AND logType = <cfqueryparam cfsqltype="cf_sql_varchar" value="logout" />)
      AS logoutTime
      FROM logTable
   </cfquery>

   [ancillary output - use your DateDiff here with getSessionInfo.loginTime and getSessionInfo.logoutTime as your two date/times and use the data as you need]
</cfoutput>

Мой SQL в этом вопросе может быть немного неправильным, но, по крайней мере, он указывает вам правильное направление ... Надеюсь, это поможет ... не стесняйтесь связаться со мной из списка для получения дополнительных объяснений.

0 голосов
/ 12 октября 2010

Как и другие предлагали, изменение структуры таблицы - лучший подход в долгосрочной перспективе.Попытка создать пару записей журнала (без соответствующего ключа) трудна, а иногда и невозможна.Слегка измененная структура будет проще запрашивать и даст более точные результаты.Однако, если вы абсолютно не можете изменить таблицу, возможно, можно рассчитать грубый итог - ЕСЛИ идентификатор вашей записи числовой / последовательный.

Предполагается, что запись "logout" всегда вставляется после a "login".Таким образом, идентификатор записи выхода из системы всегда будет больше, чем соответствующий «логин».Подзапрос может преобразовать регистрационную информацию в пары: то есть текущая и следующая регистрационная запись.Соответствующий идентификатор записи «logout» будет находиться в этом диапазоне.После того, как вы сопоставили вход / выход из системы, используйте функции даты / времени, чтобы рассчитать время, прошедшее в минутах.Затем SUM () значения и отформатируйте результаты, как вы хотите.Примечание. Очевидно, что правильная индексация таблицы должна .

Тем не менее, этот метод дает только оценку.У него есть несколько недостатков:

  • Некоторые базы данных не очень хорошо оптимизируют подзапросы.Таким образом, даже при использовании индексов производительность запросов может быть довольно низкой, если задействовано много данных.
  • Для идентификации полагается исключительно на идентификатор записи.
  • Не учитывает случайные записи о выходе из системы или ошибочные / дубликаты.Так что он может быть менее точным, чем другие методы
  • Требуется больше извилистых sql, чем альтернативные структуры

В любом случае, я не уверен в синтаксисе MySQL в голове.Но игнорируя специфические функции MS Sql Server, это должно быть близко.Производительность в MS SQL была приличной с правильными индексами и около 100K записей.

SELECT  SUM(DateDiff(n, li.LogTime, lo.LogTime)) AS TotalTimeInMinutes
FROM    (
            SELECT  li.RecordID, li.UserID, li.LogType, li.LogTime,
                   (    SELECT MIN(t.RecordID) FROM  YourTable t
                        WHERE t.UserID   = li.UserID
                        AND   t.LogType  = li.logType
                        AND   t.RecordID > li.RecordID
                    ) AS NextRecordID
            FROM   YourTable li
            WHERE  li.UserID = 123
            AND    li.LogType = 'login'
        ) 
        li INNER JOIN YourTable lo ON lo.UserID = li.UserID
             AND lo.LogType = 'logout'
             AND lo.RecordID BETWEEN li.RecordID AND li.NextRecordID
0 голосов
/ 11 октября 2010

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

Когда начинается сессия - создайте запись в таблице sessions, которая может выглядеть так:

id (int) auto-incremented PK
sessionid (varchar) -- optional, session id string from ColdFusion
userid (int) FK
session_start (datetime) -- filled when created
last_request (datetime)

Первичный ключ сохраняется в сеансе пользователя при создании записи.

Когда пользователь делает запрос - обновите атрибут last_request.

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

Дополнительным преимуществом этого подхода является то, что вы можете очень легко получать агрегированные данные на пользователя. Например, будет выбрано количество секунд (не проверено, возможно, глючит):

<cfquery datasource="mydsn" name="qGetUserData">
    select userid, sum(unix_timestamp(last_request) - unix_timestamp(session_start)) as timespan
    from sessions 
    group by userid
</cfquery>

Фильтрация по периодам также проста - просто добавьте предложение where session_start ..., то же самое для фильтрации по конкретным пользователям.

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