Cách nhanh chóng và tiện lợi: http://sqlfiddle.com/#!1/bd2f6/21 Tôi đã đặt tên cột của mình là tstamp
thay vì timestamp
của bạn
with t as (
select
generate_series(mitstamp,matstamp,'15 minutes') as int,
duration
from
(select min(tstamp) mitstamp, max(tstamp) as matstamp from tmp) a,
(select duration from tmp group by duration) b
)
select
int as timestampwindowstart,
t.duration,
count(tmp.duration)
from
t
left join tmp on
(tmp.tstamp >= t.int and
tmp.tstamp < (t.int + interval '15 minutes') and
t.duration = tmp.duration)
group by
int,
t.duration
order by
int,
t.duration
Giải thích ngắn gọn:
- Tính dấu thời gian tối thiểu và tối đa
- Tạo khoảng thời gian 15 phút giữa tối thiểu và tối đa
- Kết quả kết hợp chéo với các giá trị duy nhất về thời lượng
- Dữ liệu gốc kết hợp trái (kết hợp trái là quan trọng, vì điều này sẽ giữ tất cả kết hợp có thể có trong đầu ra và sẽ có
null
trong đó thời lượng không tồn tại trong khoảng thời gian nhất định. - Tổng hợp dữ liệu.
count(null)=0
Trong trường hợp bạn có nhiều bảng hơn và nên áp dụng thuật toán trên liên kết của chúng. Giả sử chúng ta có ba bảng tmp1, tmp2, tmp3
tất cả đều có cột tstamp
và duration
. Chúng tôi có thể mở rộng giải pháp trước đó:
with
tmpout as (
select * from tmp1 union all
select * from tmp2 union all
select * from tmp3
)
,t as (
select
generate_series(mitstamp,matstamp,'15 minutes') as int,
duration
from
(select min(tstamp) mitstamp, max(tstamp) as matstamp from tmpout) a,
(select duration from tmpout group by duration) b
)
select
int as timestampwindowstart,
t.duration,
count(tmp.duration)
from
t
left join tmpout on
(tmp.tstamp >= t.int and
tmp.tstamp < (t.int + interval '15 minutes') and
t.duration = tmp.duration)
group by
int,
t.duration
order by
int,
t.duration
Bạn thực sự nên biết with
mệnh đề trong PostgreSQL. Đây là khái niệm vô giá cho bất kỳ phân tích dữ liệu nào trong PostgreSQL.