Вопрос

Добрый день все.

У меня есть эта среда: на MySQL DB каждый раз, когда пользователь входит в систему на сайте, она создается новая строка с его именем и временем, когда он входит в систему. Поскольку система является взаимной эксклюзивной, будет только пользователь в определенное время, и если новый пользователь появится, один зарегистрирован отключен.

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

user  |       timestamp     |
------------------------------
alpha | 2013-01-19 03:14:07
beta  | 2013-01-20 11:24:04
alpha | 2013-01-21 02:11:37
alpha | 2013-01-21 03:10:31    <---- a user could login twice, it is normal
gamma | 2013-01-21 11:24:04
beta  | 2013-01-21 11:25:00

Я хотел бы спросить ваше мнение, так как есть много логинов, что является лучшим способом рассчитать общее время зарегистрированного пользователя? В этом примере «Гамма» будет иметь время входа в систему 56 секунд, и последний вход в бета может быть проигнорирован, поскольку он будет онлайн во время выполнения этой проверки. Таким образом, «бета» будет иметь только одну запись.

Есть ли способ, который вы рассчитываете через запрос? Или лучше добавить колонку «Время онлайн» и позволить SISTEM рассчитывать каждый раз, когда пользователь выходит из системы, сколько времени потратило в Интернете?

Это было полезно?

Решение

Это требует самостоятельного положения, если вы хотите сделать это в MySQL. Это боль в шее, чтобы сделать самообучение, потому что MySQL не имеет встроенной функции Rownum. Но это все еще выполнимо.

Во -первых, нам нужно создать подзадачу, чтобы создать виртуальную таблицу, имитирующую SELECT rownum, user, timestamp FROM login Что мы можем сделать так. http://sqlfiddle.com/#!2/bf6ef/2/0

SELECT @a:=@a+1 AS rownum, user, timestamp
    FROM (
        SELECT user, timestamp
          FROM login
         ORDER BY timestamp
    ) C,
    (SELECT @a:=0) s

Далее нам нужно сделать самостоятельный уряд этой виртуальной таблицы в копию себя. Что мы хотим в этом наборе результатов, так это список всех последовательных пар строк в таблице. Этот запрос - волос - он ставит структурированный в Структурированный язык запросов. Анкет Но это работает. Вот: http://sqlfiddle.com/#!2/bf6ef/4/0

SELECT first.user AS fuser, 
       first.timestamp AS ftimestamp,
       second.user AS suser,
       second.timestamp as stimestamp,
       TIMESTAMPDIFF(SECOND, first.timestamp, second.timestamp) AS timeloggedin

  FROM (
       SELECT @a:=@a+1 AS rownum, user, timestamp
         FROM (
             SELECT user, timestamp
               FROM login
           ORDER BY timestamp
              ) C,
          (SELECT @a:=0) s
        ) AS first
  JOIN (
       SELECT @b:=@b+1 AS rownum, user, timestamp
         FROM (
             SELECT user, timestamp
               FROM login
           ORDER BY timestamp
              ) C,
          (SELECT @b:=0) s
        ) AS second ON first.rownum+1 = second.rownum

Весь трюк для сравнения последовательных рядов - это

SELECT (virtual_table) AS first
  JOIN (virtual_table) AS second ON first.rownum+1 = second.rownum

Запрос шаблон. Rownum+1 = Rownum Thing собирает ряды с последовательными номерами строк вместе.

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

  SELECT user, SUM(timeloggedin) AS timeloggedin
    FROM (
          /* the self-joined query */
         ) AS selfjoin
   GROUP BY user
   ORDER BY user

Это выглядит так: http://sqlfiddle.com/#!2/bf6ef/5/0

Это весь запрос, собранный.

SELECT user, SUM(timeloggedin) AS timeloggedin
  FROM (
      SELECT first.user AS user, 
             TIMESTAMPDIFF(SECOND, first.timestamp, second.timestamp) AS timeloggedin
        FROM (
             SELECT @a:=@a+1 AS rownum, user, timestamp
         FROM (
                   SELECT user, timestamp
                     FROM login
                 ORDER BY timestamp
                    ) C,
                (SELECT @a:=0) s
              ) AS first
        JOIN (
             SELECT @b:=@b+1 AS rownum, user, timestamp
               FROM (
                   SELECT user, timestamp
                     FROM login
                 ORDER BY timestamp
                    ) C,
                (SELECT @b:=0) s
              ) AS second ON first.rownum+1 = second.rownum
         ) AS selfjoin
   GROUP BY user
   ORDER BY user

Это не реально для кого -то, привыкшего к процедурной, алгоритмической, мышлению. Но именно так вы делаете этот вид последовательного сравнения в SQL.

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

Попробуйте с этим ... меньше или больше - решение вашей проблемы ...

    CREATE TABLE `matteo` (
      `user` varchar(20) DEFAULT NULL,
      `timestamp` int(11) DEFAULT NULL
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1;

    INSERT INTO matteo(user, `timestamp`) VALUES ('alpha', 7);
    INSERT INTO matteo(user, `timestamp`) VALUES ('beta', 9);
    INSERT INTO matteo(user, `timestamp`) VALUES ('alpha', 17);
    INSERT INTO matteo(user, `timestamp`) VALUES ('alpha', 27);
    INSERT INTO matteo(user, `timestamp`) VALUES ('gamma', 77);
    INSERT INTO matteo(user, `timestamp`) VALUES ('beta', 97);

    select a.*,b.*,b.`timestamp`-a.`timestamp` as delta
    from
    (SELECT @rownum := @rownum + 1 AS id,t.*
          FROM matteo t,(SELECT @rownum := 0) r) a
    join
    (SELECT @rownum2 := @rownum2 + 1 AS id,t.*
          FROM matteo t,(SELECT @rownum2 := 0) r) b 
    where a.id=b.id-1

:-) Увидимся в понедельник !!!

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top