Reputation: 527
I have an events table, i need to get whenever an overspeed alarm has gone for over 2 minutes for any deviceid
and flag them with "emailSent"=1
.
What i'm doing is, grab all the events per vehicle like so SELECT * FROM tc_events tm where "emailSent" = 0 and date(servertime) = date(now());
and then 1 by 1 comparing to its last known value like so
SELECT *
FROM tc_events tm
where deviceid = ?
and id not in (?)
and "attributes" = '{"alarm":"overspeed"}'
and servertime > NOW() - INTERVAL '2 minute'
and date(servertime) = date(now())
limit 1;
Maybe you guys can help me to get it in one single query.
CREATE TABLE public.tc_events (
id serial NOT NULL,
"type" varchar(128) NOT NULL,
servertime timestamp NOT NULL,
deviceid int4 NULL,
positionid int4 NULL,
geofenceid int4 NULL,
"attributes" varchar(4000) NULL,
maintenanceid int4 NULL,
"emailSent" int4 NULL DEFAULT 0,
CONSTRAINT tc_events_pkey PRIMARY KEY (id)
);
id |type |servertime |deviceid|positionid|geofenceid|attributes |maintenanceid|emailSent|
------|-----|-------------------|--------|----------|----------|---------------------|-------------|---------|
631014|alarm|2020-09-03 20:46:36| 962| 8162779| |{"alarm":"overspeed"}| | 0|
630980|alarm|2020-09-03 20:42:43| 962| 8162521| |{"alarm":"overspeed"}| | 0|
630971|alarm|2020-09-03 20:40:08| 962| 8162385| |{"alarm":"overspeed"}| | 0|
607651|alarm|2020-09-02 14:46:13| 557| 7871167| |{"alarm":"overspeed"}| | 1|
607616|alarm|2020-09-02 14:44:33| 557| 7870620| |{"alarm":"overspeed"}| | 1|
591124|alarm|2020-09-01 17:13:05| 239| 7652421| |{"alarm":"overspeed"}| | 0|
590225|alarm|2020-09-01 16:30:31| 148| 7642031| |{"alarm":"overspeed"}| | 0|
590172|alarm|2020-09-01 16:28:35| 148| 7641467| |{"alarm":"overspeed"}| | 0|
588176|alarm|2020-09-01 15:14:42| 148| 7619691| |{"alarm":"overspeed"}| | 0|
582210|alarm|2020-09-01 11:34:11| 725| 7543204| |{"alarm":"overspeed"}| | 0|
Upvotes: 0
Views: 71
Reputation: 656666
Assuming that the mere existence of another overspeed alarm within the past two minutes constitutes "ongoing", EXISTS
can do the job:
SELECT *
FROM tc_events tm
WHERE deviceid = ?
AND id not in (?)
AND attributes = '{"alarm":"overspeed"}'
AND servertime > NOW() - INTERVAL '2 minute' -- only look at very recent rows?
AND date(servertime) = date(now()) -- why? local midnight cancels "ongoing"?
AND EXISTS (
SELECT FROM tc_events
WHERE deviceid = tm.deviceid
-- AND id not in (?) -- exclude here, too?
AND id <> tm.id -- exclude self
AND attributes = '{"alarm":"overspeed"}'
AND servertime <= tm.servertime -- same time possible?
AND servertime >= tm.servertime - interval '2 minute'
);
This reports "ongoing" events repeatedly for every new row.
Aside, your attributes
column looks like a JSON document, and varchar(4000)
is probably not the best way to store it ...
Upvotes: 1