This problem could be easier to solve with QuickSight if functions such as lead()
, lag()
and windowXXX()
functions would support PRE_FILTER and PRE_AGG aggregation level (feature request alert
)
So my first suggestion would be to see if you could get this populated into your dataset (example via a window function from the underlying database).
Nevertheless, failing this, luckily this problem can still be solved totally within QuickSight.
The idea is to sum the differences in time between each 2 readings. Each reading’s timestamp is first converted to a difference in seconds from the first reading’s time. Then this number is is assigned a + or - sign (determined by the uptime_metric_multiplier
field). And finally all these are added together to give you the total_uptime
. There is some additional logic to cater for cases where the last reading needs to be ignored (see comment at the bottom).
You need to add the following calculated fields:
run_status_int
ifelse(run_status = 'On', 1, 0)
rank_asc
denseRank([timestamp ASC], [model, model_serial_number], PRE_AGG)
rank_desc
denseRank([timestamp DESC], [model, model_serial_number], PRE_AGG)
first_value
minOver(ifelse({rank_asc} = 1, run_status_int, null), [model,model_serial_number], PRE_AGG)
first_timestamp
minOver(timestamp, [model,model_serial_number], PRE_AGG)
diff_first_timestamp
dateDiff({first_timestamp}, {timestamp}, 'SS')
uptime_metric_multiplier
ifelse(
{rank_desc} = 1 AND run_status_int = 1 , 0, /* Ignore last On metric */
{first_value} = 1,
ifelse(
{rank_asc} % 2 = 0, 1, /* Even metrics are Off */
{rank_asc} % 2 = 1, -1, /* Odd metrics are On */
null
),
{first_value} = 0,
ifelse(
{rank_asc} % 2 = 0, -1, /* Even metrics are On */
{rank_asc} % 2 = 1, 1, /* Odd metrics are Off */
null
),
null
)
total_uptime
sumOver({diff_first_timestamp} * {uptime_metric_multiplier}, [model, {model_serial_number}], PRE_AGG)
This will give you the total uptime. I will leave the definition of downtime for you to figure out
(it should not be difficult given the above). Also, worth noting here that if a sensor’s last value was On, then currently that last value is ignored since we cannot know the duration for which it remained on.