0

I have a table that allows users to stores different metrics for devices. devices can be different types (think IoT) and have different metrics.

e.g. a fleet tracking device might have speed, distanceTravelled, tripDuration whilst agricultural sensor might have temperature, humidity.

Note that there isn't necessarily the same amount of metrics within a single asset. e.g. tripDuration might only be updated a handful of times per day whereas speed could be updated twice a minute.

create table metric_history
(
  device_id     uuid not null,
  timestamp     timestamp,
  metric_name   text,
  value         double precision
);

I'm currently working on a system to allow users to run custom historical reports on their devices. These reports are aggregate reports.

For example, a fleet tracking customer might want to create a report showing for each of his devices for the current week:

  • Max Speed: MAX(speed)
  • Average Speed: AVG(speed)
  • Number of Trips: COUNT(tripDuration)
  • Average Trip Length: AVG(tripDuration)
  • etc

How will I go about querying something like this (hopefully somewhat efficiently)? Struggling to come up with a way to approach it.

1
  • So just SELECT device_id, whatever_aggreate(value) FROM metric_history WHERE metric_name = '…' GROUP BY device_id? Commented Nov 7, 2019 at 2:16

2 Answers 2

2

Use the FILTER clause, e.g.:

select
    device_id,
    max(value) filter (where metric_name = 'speed') as max_speed,
    avg(value) filter (where metric_name = 'speed') as avg_speed,
    count(value) filter (where metric_name = 'tripDuration') as number_of_trips
from metric_history
group by device_id
Sign up to request clarification or add additional context in comments.

Comments

0

If you want to get all values in same select you can do that:

SELECT MAX(CASE WHEN device_id=X THEN value ELSE 0 END) AS speed,
       AVG(CASE WHEN device_id=Y THEN value ELSE null END) AS tripDuration
  FROM metric_history

P.S.: When you discard a value in AVG, you need to set null, to not consider the element in average.

2 Comments

Better just MAX(value) FILTER (WHERE device_id=X) and AVG(value) FILTER (WHERE device_id=Y). Btw the advice you gave about avg would hold the same for other aggregates, wouldn't it?
Interesting approach, the filter function. About the advice, yes. Just supposed that the speed wouldn't be negative. But, looking for the generalist perspective, your perspective about the nulls is more reliable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.