Reputation: 45
I'm using PostgreSQL 9.3 with a table of approx 7M rows.
I want to get a count of the number of records in a table on a per-device_group, per-day basis.
I'd like my result set to look like this:
device_group.id | date | count
-------------------------------------
123 | 2013-11-28| 45
123 | 2013-11-29| 37
124 | 2013-11-28| 4
124 | 2013-11-29| 23
125 | 2013-11-28| 3
Where each device_group has a daily count available as a record in the result set.
Ideally, I can pass a start and end date to determine how many date records there should be per device_group in the result set.
I don't mind if the result set omits records with a count of zero.
A basic form of the tables looks like this:
CREATE TABLE session (
id SERIAL PRIMARY KEY,
acctstarttime TIMESTAMP,
deviceid INTEGER (FOREIGN KEY)
);
CREATE TABLE device_group (
id SERIAL PRIMARY KEY,
name TEXT
);
CREATE TABLE device (
id SERIAL PRIMARY KEY,
device_group_id INTEGER (FOREIGN KEY)
name TEXT
);
I've worked with windowing functions, and I can get a global number broken down by date, or a number by device_group_id, but not combined... and that's where i'm stuck.
What i've been working with so far:
SELECT
device_group_id,
COUNT(s.id)
OVER (PARTITION BY deviceid)
FROM session s
LEFT JOIN device d ON s.deviceid = d.id
WHERE acctstarttime > '2013-11-01' AND acctstarttime < '2013-11-28'
ORDER BY device_group_id;
and
SELECT
TO_TIMESTAMP( EXTRACT ('epoch' FROM acctstarttime)::int / (86400) * 86400 ) AS timeslice,
COUNT(username)
FROM session
WHERE acctstarttime > '2013-11-01' AND acctstarttime < '2013-11-28'
GROUP BY timeslice
ORDER BY timeslice ASC;
Upvotes: 1
Views: 1356
Reputation: 36087
For this task a simple GROUP BY query is sufficient:
select d.device_group_id,
date_trunc( 'day', s.acctstarttime ) date,
count(*)
from device d
join session s
on d.id = s.deviceid
group by d.device_group_id,
date_trunc( 'day', s.acctstarttime )
order by d.device_group_id, date
;
and another version with the WHERE clause
select d.device_group_id,
date_trunc( 'day', s.acctstarttime ) date,
count(*)
from device d
join session s
on d.id = s.deviceid
where acctstarttime between
to_timestamp('2013-01-01', 'yyyy-mm-dd')
and
to_timestamp('2014-01-01', 'yyyy-mm-dd')
group by d.device_group_id,
date_trunc( 'day', s.acctstarttime )
order by d.device_group_id, date
;
demo: --> http://www.sqlfiddle.com/#!15/4a3ef/7
Upvotes: 1