CTE đệ quy
Vì mỗi hàng phụ thuộc vào hàng trước nên khó có thể giải quyết bằng cách tiếp cận dựa trên tập hợp. Chuyển đến CTE đệ quy (là SQL chuẩn):
WITH RECURSIVE cte AS (
(SELECT ts FROM tbl
ORDER BY ts
LIMIT 1)
UNION ALL
(SELECT t.ts
FROM cte c
JOIN tbl t ON t.ts >= c.ts + interval '5 min'
ORDER BY t.ts
LIMIT 1)
)
SELECT * FROM cte ORDER BY ts;
Lưu ý cập nhật từ bản nháp đầu tiên của tôi:
Các hàm tổng hợp không được phép trong CTE đệ quy. Tôi đã thay thế bằng ORDER BY
/ LIMIT 1
, sẽ nhanh khi được hỗ trợ bởi chỉ mục trên ts
.
Dấu ngoặc đơn quanh mỗi chân của UNION
truy vấn là cần thiết để cho phép LIMIT
, nếu không sẽ chỉ được phép một lần ở cuối UNION
truy vấn.
Hàm PL / pgSQL
Một giải pháp thủ tục (ví dụ với hàm plpgsql) lặp lại qua bảng đã sắp xếp có thể sẽ nhanh hơn rất nhiều, vì nó có thể thực hiện với một lần quét bảng:
CREATE OR REPLACE FUNCTION f_rowgrid(i interval)
RETURNS SETOF timestamp AS
$func$
DECLARE
_this timestamp;
_last timestamp := '-infinity'; -- init so that 1 row passes
BEGIN
FOR _this IN
SELECT ts FROM tbl ORDER BY 1
LOOP
IF _this >= _last + i THEN
RETURN NEXT _this;
_last := _this;
END IF;
END LOOP;
END
$func$ LANGUAGE plpgsql;
Gọi:
SELECT * FROM f_rowgrid('5 min')
SQL Fiddle thể hiện cả hai.
Đây là một ví dụ phức tạp hơn cho loại hàm plpgsql này:
Có thể dễ dàng trở thành chung chung với SQL động và EXECUTE
để làm việc cho các bảng tùy ý.