问题
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