It looks like you are trying to keep a cumulative count, bracketed by the hour. To do that, you can use a window function, like this:
SELECT DISTINCT
A.hour AS hour,
SUM(COALESCE(M.include, 0)) OVER (ORDER BY A.hour) AS cumulative_count
FROM ( -- get all records, with 0 for include
SELECT
name,
hour,
0 AS include
FROM
table
) A
LEFT JOIN
( -- get the record with lowest `hour` for each `name`, and 1 for include
SELECT
name,
MIN(hour) AS hour,
1 AS include
FROM
table
GROUP BY
name
) M
ON M.name = A.name
AND M.hour = A.hour
;
There might be a simpler way, but this should yield the correct answer in general.
Explanation:
This uses 2 subqueries against the same input table
, with a derived field called include
to keep track of which records should contribute to the final total for each bucket. The first subquery simply takes all records in the table and assigns 0 AS include
. The second subquery finds all unique name
s and the lowest hour
slot in which that name
appears, and assigns them 1 AS include
. The 2 subqueries are LEFT JOIN
'ed by the enclosing query.
The outermost query does a COALESCE(M.include, 0)
to fill in any NULL
's produced by the LEFT JOIN
, and those 1
's and 0
's are SUM
'ed and windowed by hour
. This needs to be a SELECT DISTINCT
rather than using a GROUP BY
becuse a GROUP BY
will want both hour
and include
listed, but it ends up collapsing every record in a given hour
group into a single row (still with include=1
). The DISTINCT
is applied after the SUM
so it will remove duplicates without discarding any input rows.