简体   繁体   English

Postgresql时间片/窗口查询

[英]Postgresql Timeslice/Windowing Query

I'm using PostgreSQL 9.3 with a table of approx 7M rows. 我正在将PostgreSQL 9.3与大约7M行的表一起使用。

I want to get a count of the number of records in a table on a per-device_group, per-day basis. 我想按每天,每个device_group来获取表中记录的数量。

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. 每个device_group都有一个每日计数作为结果集中的记录。

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. 理想情况下,我可以传递开始和结束日期来确定结果集中每个device_group应该有多少个日期记录。

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. 我已经使用了窗口函数,并且可以按日期或按device_group_id分解得到一个全局数字,但不能将其组合在一起……这就是我遇到的问题。

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;

For this task a simple GROUP BY query is sufficient: 对于此任务,一个简单的GROUP BY查询就足够了:

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 以及带有WHERE子句的另一个版本

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 演示:-> http://www.sqlfiddle.com/#!15/4a3ef/7

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM