SQLLite time entry and time exit from eventime

送分小仙女□ 提交于 2020-01-15 09:13:30

问题


I have two tables, DATA and EVENTS, with the following data:

EVENTS
EventIndex  ObjID   LocID   EventData   EventTime       EventType
83707365    3519434 10376   0           2013-05-19 11:32:11 137
83707849    3519434 10374   0           2013-05-19 11:35:18 137 
83714233    888799  10376   0           2013-05-19 12:24:45 137 
83715200    888799  10184   0           2013-05-19 12:32:18 137

DATA
EventIndex  TagName TagValue    
83714233    ObjName Peter
83714233    LocName H118
83715200    ObjName Peter
83715200    LocName H116
83707365    ObjName John
83707365    LocName H118
83707849    ObjName John
83707849    LocName H116

Where do I start with a SQL SQLLite query?

I want to get the results:

Name   Location  Entry      Exit        Total
Peter  H118      12:24:45   12:32:18    00:07:33
John   H118      11:32:11   11:35:18    00:03:07

Hi meewoK, can give the following case:

Name Location Entry Exit Total
Peter H118 12:24:45 12:32:18 00:07:33
John H118 11:32:11 11:35:18 00:03:07
John H118 11:44:52 11:45:27 00:00:35
John H118 12:31:15 12:32:46 00:01:31

and I'm trying to modify your query and I can not find the solution. Thanks

This code works in SQL SERVER:

SELECT E.EventIndex, N.tagvalue AS Name, L.tagvalue AS Location, E.eventtime AS Entry, NEV.[Exit]
FROM
[EVENTS] E
INNER JOIN [DATA] N ON E.EventIndex = N.eventindex AND N.tagname = 'ObjName'
INNER JOIN [DATA] L ON E.EventIndex = L.eventindex AND L.tagname = 'LocName'
OUTER APPLY (
SELECT TOP (1) NE.eventtime AS [Exit]
FROM
[EVENTS] NE
INNER JOIN [DATA] NL ON NE.EventIndex = NL.eventindex AND NL.tagname = 'ObjName'
WHERE
NE.EventIndex > E.EventIndex
AND NL.tagvalue = N.tagvalue
ORDER BY
NE.EventIndex

) NEV  

WHERE L.tagvalue = 'H118'

Someone could help me to pass it to SQLite? Thanks


回答1:


Here is a quick SQL dump for working on the table.

CREATE TABLE EVENTS (EventIndex int, objID int, eventtime datetime);
INSERT INTO "EVENTS" VALUES(83707365,3519434,'2013-05-19 11:32:11');
INSERT INTO "EVENTS" VALUES(83707849,3519434,'2013-05-19 11:35:18');
INSERT INTO "EVENTS" VALUES(83714233,888799,'2013-05-19 12:24:25');
INSERT INTO "EVENTS" VALUES(83714233,888799,'2013-05-19 12:32:18');
CREATE TABLE DATA (eventindex int, tagname char, tagvalue char);
INSERT INTO "DATA" VALUES(83714233,'ObjName','Peter');
INSERT INTO "DATA" VALUES(83714233,'LocName','H118');
INSERT INTO "DATA" VALUES(83715200,'ObjName','Peter');
INSERT INTO "DATA" VALUES(83715200,'LocName','H118');
INSERT INTO "DATA" VALUES(83707365,'ObjName','John');
INSERT INTO "DATA" VALUES(83707849,'ObjName','John');
INSERT INTO "DATA" VALUES(83707365,'LocName','H118');
INSERT INTO "DATA" VALUES(83707849,'LocName','H118');

Step 1, get the maximal and minimal eventtype for each ObjID:

SELECT ObjID, Min(EventIndex) as EventIndex, Min(EventTime) as Entry, Max(EventTime) as Exit
  FROM EVENTS GROUP BY ObjID;


ObjID    EventIndex     Entry      Exit
3519434   83707365   12:24:45  12:32:18
 888799   83714233   11:32:11  11:25:18

Now this reveals some problems with your data structure. For each ObjID, you have two EventIndex, so which one should you pick? Here, I have simply selected the first (smallest) of the two.

Step 2, because sqlite3 dislikes performing operations on aggregates, we make it into a view:

CREATE VIEW single_events AS 
SELECT ObjID, Min(EventIndex) as EventIndex, Min(EventTime) as Entry, Max(EventTime) as Exit FROM EVENTS GROUP BY ObjID;

Step 3, get the total time by operating on the view:

SELECT *, time(strftime('%s', exit) - strftime('%s', entry), 'unixepoch') as total 
  FROM single_events;
ObjID       EventIndex  Entry                Exit                 total
----------  ----------  -------------------  -------------------  ----------
888799      83714233    2013-05-19 12:24:25  2013-05-19 12:32:18  00:07:53
3519434     83707365    2013-05-19 11:32:11  2013-05-19 11:35:18  00:03:07

Step 4, merge this with DATA.

SELECT d1.TagValue as Name, d2.TagValue as Location, Entry, Exit, time(strftime('%s', exit) - strftime('%s', entry), 'unixepoch') as total
  FROM single_events
  LEFT JOIN DATA as d1 USING (EventIndex)
  LEFT JOIN DATA as d2 USING (EventIndex)
  WHERE d1.tagname = 'ObjName' AND d2.tagname = 'LocName';

Of course, if it is a very large data set, you might benefit from pouring d1 and d2 into a temporary table before running step 4.




回答2:


Something like this could get you started along nicely:

SQL Fiddle: http://www.sqlfiddle.com/#!2/6e6a7/33

SELECT d.TagValue AS Name,
       d2.TagValue AS LOCATION,
       e.eventTime AS Entry,

  ( SELECT eventtime
   FROM EVENTS e2
   WHERE e2.objID = e.objID
     AND e2.eventTime > e.eventTime LIMIT 1) AS ExitTime,
       (e.eventTime -
          ( SELECT eventtime
           FROM EVENTS e2
           WHERE e2.objID = e.objID
             AND e2.eventTime > e.eventTime LIMIT 1)) AS TotalTime
FROM events e,
     DATA d,
          DATA d2
WHERE e.eventIndex = d.eventIndex
  AND e.eventIndex = d2.eventIndex
  AND d.TagName = "ObjName"
  AND d2.TagName = "LocName"
  AND mod(
            ( SELECT count(*)
             FROM EVENTS e2
             WHERE e2.objID = e.objID
               AND e2.eventTime < e.eventTime),2) = 0
ORDER BY EventTime;

Result:

NAME    LOCATION    ENTRY                   EXITTIME                  TOTALTIME
John    H118    May, 19 2013 11:32:11+0000  May, 19 2013 11:35:18+0000  -307
Peter   H118    May, 19 2013 12:24:45+0000  May, 19 2013 12:32:18+0000  -773

I added extra events, to proof against an exit from one event being considered as an entry of another.

The above query can be optimized, if we say that an entry and exit cannot take place on different days e.g. USER enters 11.59PM and leaves 1.00AM...

SELECT d.TagValue AS Name,
       d2.TagValue AS LOCATION,
       e.eventTime AS Entry,

  ( SELECT eventtime
   FROM EVENTS e2
   WHERE e2.objID = e.objID
     AND e2.eventTime > e.eventTime LIMIT 1) AS ExitTime,
       (e.eventTime -
          ( SELECT eventtime
           FROM EVENTS e2
           WHERE e2.objID = e.objID
             AND e2.eventTime > e.eventTime AND
             DATE(e2.eventTime) = DATE(e.eventTime) LIMIT 1)) AS TotalTime
FROM events e,
     DATA d,
          DATA d2
WHERE e.eventIndex = d.eventIndex
  AND e.eventIndex = d2.eventIndex
  AND d.TagName = "ObjName"
  AND d2.TagName = "LocName"
  AND mod(
            ( SELECT count(*)
             FROM EVENTS e2
             WHERE e2.objID = e.objID
               AND e2.eventTime < e.eventTime AND
               DATE(e2.eventTime) = DATE(e.eventTime)),2) = 0
ORDER BY EventTime;

SQL Fiddle: http://www.sqlfiddle.com/#!2/6e6a7/35

This also assumes that each entry must have an exit, which is why I use the modulo operator. All Even events for a Object are an entry, all Odd events are an exit.

For more conditions, obviously the query must be modified.

Update: Using SQL Lite (no mod but %)

SQLFiddle: http://www.sqlfiddle.com/#!7/6e6a7/4

SELECT d.TagValue AS Name,
       d2.TagValue AS LOCATION,
       e.eventTime AS Entry,

  ( SELECT eventtime
   FROM EVENTS e2
   WHERE e2.objID = e.objID
     AND e2.eventTime > e.eventTime LIMIT 1) AS ExitTime,
       (e.eventTime -
          ( SELECT eventtime
           FROM EVENTS e2
           WHERE e2.objID = e.objID
             AND e2.eventTime > e.eventTime LIMIT 1)) AS TotalTime
FROM events e,
     DATA d,
          DATA d2
WHERE e.eventIndex = d.eventIndex
  AND e.eventIndex = d2.eventIndex
  AND d.TagName = "ObjName"
  AND d2.TagName = "LocName"
  AND (
            ( SELECT count(*)
             FROM EVENTS e2
             WHERE e2.objID = e.objID
               AND e2.eventTime < e.eventTime)%2) = 0
ORDER BY EventTime;


来源:https://stackoverflow.com/questions/16714039/sql-time-entry-and-time-exit-from-eventime

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!