I have this query to get records from a database:
SELECT camera_id, count(*) AS snapshot_count
FROM snapshots
WHERE created_at >= timestamp 'yesterday'
AND created_at < timestamp 'today'
GROUP BY camera_id;
I want to add some filters on created_at
to get the count
for matching rows only. E.g., the user will provide camera_id
, date
, time
, days
, for example:
From date: 2015/01/01
to date: 2015/12/30
Schedule: Monday-Friday
Timings: 9 AM to 5 pm UTC
How to apply all those to created_at
to get valid records?
Update:
I also want a count per minute. If 1 minute contains more than 1 image it shall still be counted as one. You could say, only count the first snapshot per minute.
Shortly if it is 1 per 60 minutes then it will be 1 count for 60 minutes between 9 AM to 10AM and so as on to 5PM.
Best Answer
For lack of information, assuming
created_at
is data typetimestamp
, saving UTC timestamps:The check for date seems trivial - but be careful what to include / exclude exactly with upper lower bound.
For the
time
component cast totime
:created_at::time
.For the day of week use
EXTRACT()
with the patternISODOW
(simpler for your kind of pattern thanDOW
).In case you are not aware of the difference between the data types
timestamp
andtimestamptz
and the role of thetimezone
settings and DST, now is the time to read up:Ignoring timezones altogether in Rails and PostgreSQL
Count minutes with multiple rows as one
For your added Update:
Effectively, minutes are counted in which at least one (filtered) snapshot was taken. If 7 snapshots were taken in the same minute, they still count as one.
Performance
The filters on time and day of week are not sargable. If your table is big and performance important, create functional indexes to change that - using
IMMUTABLE
expressions. Depending on your actual data type, you need to create anIMMUTABLE
wrapper function that works independently of the timezone setting, because neither the cast to time norEXTRACT()
(internally the functiondate_part()
) are definedIMMUTABLE
for various reasons.Then:
To utilize these indexes, the query hast to use the same expressions: