MySQL Get records having a time difference with other records












0















I have a MySQL DB table that logs user login and logout activities.
I need to select all user records who are not logged back in within 20 minutes after logout.



Ex: Table: Log



ID | User | Event  | Time
-----------------------------
1 | 1 | LOGIN | 10:00:00
2 | 2 | LOGIN | 10:05:00
3 | 3 | LOGIN | 10:15:00
4 | 1 | LOGOUT | 11:00:00
5 | 3 | LOGOUT | 11:01:00
6 | 2 | LOGIN | 12:20:00
7 | 2 | LOGOUT | 12:30:00
8 | 1 | LOGIN | 12:31:00
9 | 2 | LOGIN | 12:55:00


According to this sample table, the users that exceeds the gap by 20 minutes between their logouts and logins must be shown.
User 1 exceeds the 20 minute gap between record 4 and 8
User 2 exceeds the 20 minute gap between record 7 and 9



So this should show



ID | User
----------
4 | 1
8 | 1
7 | 2
9 | 2


How can I write a query to get this done?










share|improve this question

























  • If you really need to check every login/logout event for this, then your problem is a gaps and islands problem. This is difficult to solve, especially if you are using MySQL versions earlier than 8.

    – Tim Biegeleisen
    Nov 23 '18 at 10:41
















0















I have a MySQL DB table that logs user login and logout activities.
I need to select all user records who are not logged back in within 20 minutes after logout.



Ex: Table: Log



ID | User | Event  | Time
-----------------------------
1 | 1 | LOGIN | 10:00:00
2 | 2 | LOGIN | 10:05:00
3 | 3 | LOGIN | 10:15:00
4 | 1 | LOGOUT | 11:00:00
5 | 3 | LOGOUT | 11:01:00
6 | 2 | LOGIN | 12:20:00
7 | 2 | LOGOUT | 12:30:00
8 | 1 | LOGIN | 12:31:00
9 | 2 | LOGIN | 12:55:00


According to this sample table, the users that exceeds the gap by 20 minutes between their logouts and logins must be shown.
User 1 exceeds the 20 minute gap between record 4 and 8
User 2 exceeds the 20 minute gap between record 7 and 9



So this should show



ID | User
----------
4 | 1
8 | 1
7 | 2
9 | 2


How can I write a query to get this done?










share|improve this question

























  • If you really need to check every login/logout event for this, then your problem is a gaps and islands problem. This is difficult to solve, especially if you are using MySQL versions earlier than 8.

    – Tim Biegeleisen
    Nov 23 '18 at 10:41














0












0








0








I have a MySQL DB table that logs user login and logout activities.
I need to select all user records who are not logged back in within 20 minutes after logout.



Ex: Table: Log



ID | User | Event  | Time
-----------------------------
1 | 1 | LOGIN | 10:00:00
2 | 2 | LOGIN | 10:05:00
3 | 3 | LOGIN | 10:15:00
4 | 1 | LOGOUT | 11:00:00
5 | 3 | LOGOUT | 11:01:00
6 | 2 | LOGIN | 12:20:00
7 | 2 | LOGOUT | 12:30:00
8 | 1 | LOGIN | 12:31:00
9 | 2 | LOGIN | 12:55:00


According to this sample table, the users that exceeds the gap by 20 minutes between their logouts and logins must be shown.
User 1 exceeds the 20 minute gap between record 4 and 8
User 2 exceeds the 20 minute gap between record 7 and 9



So this should show



ID | User
----------
4 | 1
8 | 1
7 | 2
9 | 2


How can I write a query to get this done?










share|improve this question
















I have a MySQL DB table that logs user login and logout activities.
I need to select all user records who are not logged back in within 20 minutes after logout.



Ex: Table: Log



ID | User | Event  | Time
-----------------------------
1 | 1 | LOGIN | 10:00:00
2 | 2 | LOGIN | 10:05:00
3 | 3 | LOGIN | 10:15:00
4 | 1 | LOGOUT | 11:00:00
5 | 3 | LOGOUT | 11:01:00
6 | 2 | LOGIN | 12:20:00
7 | 2 | LOGOUT | 12:30:00
8 | 1 | LOGIN | 12:31:00
9 | 2 | LOGIN | 12:55:00


According to this sample table, the users that exceeds the gap by 20 minutes between their logouts and logins must be shown.
User 1 exceeds the 20 minute gap between record 4 and 8
User 2 exceeds the 20 minute gap between record 7 and 9



So this should show



ID | User
----------
4 | 1
8 | 1
7 | 2
9 | 2


How can I write a query to get this done?







mysql sql time






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 26 '18 at 11:51









Salman A

185k67344441




185k67344441










asked Nov 23 '18 at 10:19









TechyTeeTechyTee

82121130




82121130













  • If you really need to check every login/logout event for this, then your problem is a gaps and islands problem. This is difficult to solve, especially if you are using MySQL versions earlier than 8.

    – Tim Biegeleisen
    Nov 23 '18 at 10:41



















  • If you really need to check every login/logout event for this, then your problem is a gaps and islands problem. This is difficult to solve, especially if you are using MySQL versions earlier than 8.

    – Tim Biegeleisen
    Nov 23 '18 at 10:41

















If you really need to check every login/logout event for this, then your problem is a gaps and islands problem. This is difficult to solve, especially if you are using MySQL versions earlier than 8.

– Tim Biegeleisen
Nov 23 '18 at 10:41





If you really need to check every login/logout event for this, then your problem is a gaps and islands problem. This is difficult to solve, especially if you are using MySQL versions earlier than 8.

– Tim Biegeleisen
Nov 23 '18 at 10:41












2 Answers
2






active

oldest

votes


















1














This answers the question:




I need to select all user records who are not logged back in within 20 minutes after logout.




select lo.*
from (select l.*,
(select min(l2.time)
from logs l2
where l2.user = l.user and l2.time > l.time and
l2.event = 'LOGIN'
) as next_login_time
from logs l
where l.event = 'LOGOUT'
) lo
where next_login_time > time + interval 20 minute;


Your sample results include login results. It is unclear how those are defined, based on the question that you asked.






share|improve this answer































    1














    You seem to be interested in getting both rows if they are 20 minutes apart. The following tries to emulate LEAD and LAG:



    SELECT * FROM (
    SELECT *, (
    SELECT CASE WHEN EVENT = 'LOGOUT' AND main.Event = 'LOGIN' THEN TimeDIFF(main.Time, Time) END
    FROM t AS prev
    WHERE User = main.User AND Time < main.Time
    ORDER BY Time DESC
    LIMIT 1
    ) AS diff_lag, (
    SELECT CASE WHEN EVENT = 'LOGIN' AND main.Event = 'LOGOUT' THEN TimeDIFF(Time, main.Time) END
    FROM t AS next
    WHERE User = main.User AND Time > main.Time
    ORDER BY Time ASC
    LIMIT 1
    ) AS diff_lead
    FROM t AS main
    ) x
    WHERE diff_lag > '00:20:00' OR diff_lead > '00:20:00'


    Alternatively, try the following approach which seems to work except that it puts both rows together:



    SELECT *
    FROM t AS o
    INNER JOIN t AS i ON o.User = i.User AND o.Time < i.Time -- join logouts with potential logins
    LEFT JOIN t AS x ON o.User = x.User AND o.Time < x.Time AND x.Time < i.Time -- any row present between logout and login
    WHERE o.Event = 'LOGOUT' AND i.Event = 'LOGIN' AND x.ID IS NULL AND TIMEDIFF(i.Time, o.Time) > '00:20:00'





    share|improve this answer


























      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53444778%2fmysql-get-records-having-a-time-difference-with-other-records%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      1














      This answers the question:




      I need to select all user records who are not logged back in within 20 minutes after logout.




      select lo.*
      from (select l.*,
      (select min(l2.time)
      from logs l2
      where l2.user = l.user and l2.time > l.time and
      l2.event = 'LOGIN'
      ) as next_login_time
      from logs l
      where l.event = 'LOGOUT'
      ) lo
      where next_login_time > time + interval 20 minute;


      Your sample results include login results. It is unclear how those are defined, based on the question that you asked.






      share|improve this answer




























        1














        This answers the question:




        I need to select all user records who are not logged back in within 20 minutes after logout.




        select lo.*
        from (select l.*,
        (select min(l2.time)
        from logs l2
        where l2.user = l.user and l2.time > l.time and
        l2.event = 'LOGIN'
        ) as next_login_time
        from logs l
        where l.event = 'LOGOUT'
        ) lo
        where next_login_time > time + interval 20 minute;


        Your sample results include login results. It is unclear how those are defined, based on the question that you asked.






        share|improve this answer


























          1












          1








          1







          This answers the question:




          I need to select all user records who are not logged back in within 20 minutes after logout.




          select lo.*
          from (select l.*,
          (select min(l2.time)
          from logs l2
          where l2.user = l.user and l2.time > l.time and
          l2.event = 'LOGIN'
          ) as next_login_time
          from logs l
          where l.event = 'LOGOUT'
          ) lo
          where next_login_time > time + interval 20 minute;


          Your sample results include login results. It is unclear how those are defined, based on the question that you asked.






          share|improve this answer













          This answers the question:




          I need to select all user records who are not logged back in within 20 minutes after logout.




          select lo.*
          from (select l.*,
          (select min(l2.time)
          from logs l2
          where l2.user = l.user and l2.time > l.time and
          l2.event = 'LOGIN'
          ) as next_login_time
          from logs l
          where l.event = 'LOGOUT'
          ) lo
          where next_login_time > time + interval 20 minute;


          Your sample results include login results. It is unclear how those are defined, based on the question that you asked.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 23 '18 at 12:21









          Gordon LinoffGordon Linoff

          792k36316419




          792k36316419

























              1














              You seem to be interested in getting both rows if they are 20 minutes apart. The following tries to emulate LEAD and LAG:



              SELECT * FROM (
              SELECT *, (
              SELECT CASE WHEN EVENT = 'LOGOUT' AND main.Event = 'LOGIN' THEN TimeDIFF(main.Time, Time) END
              FROM t AS prev
              WHERE User = main.User AND Time < main.Time
              ORDER BY Time DESC
              LIMIT 1
              ) AS diff_lag, (
              SELECT CASE WHEN EVENT = 'LOGIN' AND main.Event = 'LOGOUT' THEN TimeDIFF(Time, main.Time) END
              FROM t AS next
              WHERE User = main.User AND Time > main.Time
              ORDER BY Time ASC
              LIMIT 1
              ) AS diff_lead
              FROM t AS main
              ) x
              WHERE diff_lag > '00:20:00' OR diff_lead > '00:20:00'


              Alternatively, try the following approach which seems to work except that it puts both rows together:



              SELECT *
              FROM t AS o
              INNER JOIN t AS i ON o.User = i.User AND o.Time < i.Time -- join logouts with potential logins
              LEFT JOIN t AS x ON o.User = x.User AND o.Time < x.Time AND x.Time < i.Time -- any row present between logout and login
              WHERE o.Event = 'LOGOUT' AND i.Event = 'LOGIN' AND x.ID IS NULL AND TIMEDIFF(i.Time, o.Time) > '00:20:00'





              share|improve this answer






























                1














                You seem to be interested in getting both rows if they are 20 minutes apart. The following tries to emulate LEAD and LAG:



                SELECT * FROM (
                SELECT *, (
                SELECT CASE WHEN EVENT = 'LOGOUT' AND main.Event = 'LOGIN' THEN TimeDIFF(main.Time, Time) END
                FROM t AS prev
                WHERE User = main.User AND Time < main.Time
                ORDER BY Time DESC
                LIMIT 1
                ) AS diff_lag, (
                SELECT CASE WHEN EVENT = 'LOGIN' AND main.Event = 'LOGOUT' THEN TimeDIFF(Time, main.Time) END
                FROM t AS next
                WHERE User = main.User AND Time > main.Time
                ORDER BY Time ASC
                LIMIT 1
                ) AS diff_lead
                FROM t AS main
                ) x
                WHERE diff_lag > '00:20:00' OR diff_lead > '00:20:00'


                Alternatively, try the following approach which seems to work except that it puts both rows together:



                SELECT *
                FROM t AS o
                INNER JOIN t AS i ON o.User = i.User AND o.Time < i.Time -- join logouts with potential logins
                LEFT JOIN t AS x ON o.User = x.User AND o.Time < x.Time AND x.Time < i.Time -- any row present between logout and login
                WHERE o.Event = 'LOGOUT' AND i.Event = 'LOGIN' AND x.ID IS NULL AND TIMEDIFF(i.Time, o.Time) > '00:20:00'





                share|improve this answer




























                  1












                  1








                  1







                  You seem to be interested in getting both rows if they are 20 minutes apart. The following tries to emulate LEAD and LAG:



                  SELECT * FROM (
                  SELECT *, (
                  SELECT CASE WHEN EVENT = 'LOGOUT' AND main.Event = 'LOGIN' THEN TimeDIFF(main.Time, Time) END
                  FROM t AS prev
                  WHERE User = main.User AND Time < main.Time
                  ORDER BY Time DESC
                  LIMIT 1
                  ) AS diff_lag, (
                  SELECT CASE WHEN EVENT = 'LOGIN' AND main.Event = 'LOGOUT' THEN TimeDIFF(Time, main.Time) END
                  FROM t AS next
                  WHERE User = main.User AND Time > main.Time
                  ORDER BY Time ASC
                  LIMIT 1
                  ) AS diff_lead
                  FROM t AS main
                  ) x
                  WHERE diff_lag > '00:20:00' OR diff_lead > '00:20:00'


                  Alternatively, try the following approach which seems to work except that it puts both rows together:



                  SELECT *
                  FROM t AS o
                  INNER JOIN t AS i ON o.User = i.User AND o.Time < i.Time -- join logouts with potential logins
                  LEFT JOIN t AS x ON o.User = x.User AND o.Time < x.Time AND x.Time < i.Time -- any row present between logout and login
                  WHERE o.Event = 'LOGOUT' AND i.Event = 'LOGIN' AND x.ID IS NULL AND TIMEDIFF(i.Time, o.Time) > '00:20:00'





                  share|improve this answer















                  You seem to be interested in getting both rows if they are 20 minutes apart. The following tries to emulate LEAD and LAG:



                  SELECT * FROM (
                  SELECT *, (
                  SELECT CASE WHEN EVENT = 'LOGOUT' AND main.Event = 'LOGIN' THEN TimeDIFF(main.Time, Time) END
                  FROM t AS prev
                  WHERE User = main.User AND Time < main.Time
                  ORDER BY Time DESC
                  LIMIT 1
                  ) AS diff_lag, (
                  SELECT CASE WHEN EVENT = 'LOGIN' AND main.Event = 'LOGOUT' THEN TimeDIFF(Time, main.Time) END
                  FROM t AS next
                  WHERE User = main.User AND Time > main.Time
                  ORDER BY Time ASC
                  LIMIT 1
                  ) AS diff_lead
                  FROM t AS main
                  ) x
                  WHERE diff_lag > '00:20:00' OR diff_lead > '00:20:00'


                  Alternatively, try the following approach which seems to work except that it puts both rows together:



                  SELECT *
                  FROM t AS o
                  INNER JOIN t AS i ON o.User = i.User AND o.Time < i.Time -- join logouts with potential logins
                  LEFT JOIN t AS x ON o.User = x.User AND o.Time < x.Time AND x.Time < i.Time -- any row present between logout and login
                  WHERE o.Event = 'LOGOUT' AND i.Event = 'LOGIN' AND x.ID IS NULL AND TIMEDIFF(i.Time, o.Time) > '00:20:00'






                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Nov 24 '18 at 18:55

























                  answered Nov 23 '18 at 13:16









                  Salman ASalman A

                  185k67344441




                  185k67344441






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53444778%2fmysql-get-records-having-a-time-difference-with-other-records%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      這個網誌中的熱門文章

                      Tangent Lines Diagram Along Smooth Curve

                      Yusuf al-Mu'taman ibn Hud

                      Zucchini