問題陳述:
決定定義時間內先前記錄的總數中每筆記錄一行的範圍。
特定場景:
查詢:
SELECT id, date , count(*) OVER (HAVING previous_rows.date >= (date - '1 hour'::interval)) -- ? FROM test;
表:
CREATE TABLE test ( id bigint , ts timestamp );
表:
表:SELECT id, ts , count(*) OVER (ORDER BY ts RANGE '1 hour' PRECEDING EXCLUDE CURRENT ROW) FROM test ORDER BY ts;
圖片高版本:
Postgres 11 引入了改進的視窗函數框架選項,允許使用 RANGE使用 PRECEDING 和 FOLLOWING 的模式來選擇指定偏移量內的行。
SELECT id, ts , (SELECT count(*)::int - 1 FROM unnest(dates) x WHERE x >= sub.ts - interval '1h') AS ct FROM ( SELECT id, ts , array_agg(ts) OVER(ORDER BY ts) AS dates FROM test ) sub;
Postgres 10 或更早版本:
SELECT id, ts , (SELECT count(*) FROM test t1 WHERE t1.ts >= t.ts - interval '1h' AND t1.ts < t.ts) AS ct FROM test t ORDER BY ts;ROM(Roman 的查詢):
ROM(Roman 的查詢):
CREATE OR REPLACE FUNCTION running_window_ct(_intv interval = '1 hour') RETURNS TABLE (id bigint, ts timestamp, ct int) LANGUAGE plpgsql AS $func$ DECLARE cur CURSOR FOR SELECT t.ts + _intv AS ts1 , row_number() OVER (ORDER BY t.ts ROWS UNBOUNDED PRECEDING) AS rn FROM test t ORDER BY t.ts; rec record; rn int; BEGIN OPEN cur; FETCH cur INTO rec; ct := -1; -- init FOR id, ts, rn IN SELECT t.id, t.ts , row_number() OVER (ORDER BY t.ts ROWS UNBOUNDED PRECEDING) FROM test t ORDER BY t.ts LOOP IF rec.ts1 >= ts THEN ct := ct + 1; ELSE LOOP FETCH cur INTO rec; EXIT WHEN rec.ts1 >= ts; END LOOP; ct := rn - rec.rn; END IF; RETURN NEXT; END LOOP; END $func$;
ARR (計算數組元素):
SELECT * FROM running_window_ct();
COR(相關子查詢):
調用函數:基準結果:使用具有不同行數的表進行的基準測試表明,FNC 函數在性能和可擴展性方面明顯勝出。以上是如何在 PostgreSQL 中有效率地統計某個時間範圍內的前行數?的詳細內容。更多資訊請關注PHP中文網其他相關文章!