문제 설명:
정의된 시간 내에 이전 레코드의 총 개수 결정 테이블의 각 행에 대한 범위.
특정 시나리오:
쿼리:
SELECT id, date , count(*) OVER (HAVING previous_rows.date >= (date - '1 hour'::interval)) -- ? FROM test;
테이블:
CREATE TABLE test ( id bigint , ts timestamp );
Postgres 11 이상:
Postgres 11에는 향상된 창 기능 프레이밍 옵션이 도입되어 RANGE를 사용할 수 있습니다. PRECEDING 및 FOLLOWING을 사용하여 지정된 오프셋 내의 행을 선택합니다.
SELECT id, ts , count(*) OVER (ORDER BY ts RANGE '1 hour' PRECEDING EXCLUDE CURRENT ROW) FROM test ORDER BY ts;
Postgres 10 이하:
ROM(Roman의 쿼리):
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;
ARR (배열 요소 개수):
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;
COR(상관 하위 쿼리):
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$;
함수 호출:
SELECT * FROM running_window_ct();
벤치마크 결과:
행 개수가 다양한 테이블을 사용한 벤치마크 결과 FNC 기능이 성능과 확장성 측면에서 확실한 승리를 거두었습니다.
위 내용은 PostgreSQL에서 시간 범위 내에서 이전 행을 효율적으로 계산하는 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!