설명 결과는 다음 과 같은 테이블 정의가됩니다 .
CREATE TABLE tbl (
lap_id serial PRIMARY KEY
, lap_no int NOT NULL
, car_type enum NOT NULL
, race_id int NOT NULL -- REFERENCES ...
, UNIQUE(race_id, car_type, lap_no)
);
이러한 종류의 문제에 대한 일반적인 해결책
가장 긴 시퀀스를 얻으려면 (연관이있는 경우 가장 긴 1 개의 결과, 임의의 선택) :
SELECT race_id, car_type, count(*) AS seq_len
FROM (
SELECT *, count(*) FILTER (WHERE step)
OVER (ORDER BY race_id, car_type, lap_no) AS grp
FROM (
SELECT *, (lag(lap_no) OVER (PARTITION BY race_id, car_type ORDER BY lap_no) + 1)
IS DISTINCT FROM lap_no AS step
FROM tbl
) x
) y
GROUP BY race_id, car_type, grp
ORDER BY seq_len DESC
LIMIT 1;
count(*) FILTER (WHERE step)
카운트 만 TRUE
(= 다음 그룹으로 이동) 모든 새 그룹에 대해 새 숫자를 생성합니다.
SO에 대한 관련 질문, plpgsql을 사용한 절차 적 솔루션을 갖춘 하나의 답변 :
최고 요구 사항이 성능이면 plpgsql 함수는 일반적으로 단일 스캔으로 결과를 계산할 수 있기 때문에이 특정 경우에 더 빠릅니다 .
연속 번호가 더 빠름
훨씬 간단하고 빠른 버전을 위해 시퀀스 를 연속적으로 lap_no
정의 한다는 사실을 활용할 수 있습니다 .
SELECT race_id, car_type, count(*) AS seq_len
FROM (
SELECT race_id, car_type
, row_number() OVER (PARTITION BY race_id, car_type ORDER BY lap_no) - lap_no AS grp
FROM tbl
) x
GROUP BY race_id, car_type, grp
ORDER BY seq_len DESC
LIMIT 1;
연속 랩은 같은 결과를 낳습니다 grp
. 누락 된 모든 랩 grp
은 파티션 당 더 낮아집니다 .
이에 의존 (race_id, car_type, lap_no)
되고 UNIQUE NOT NULL
. NULL 값 또는 중복은 논리를 손상시킬 수 있습니다.
Jack의 더 간단한 대안에 대한 토론
잭의 버전 @ 효과적으로 모든 랩 (행)을 계산 이전의 경우 lap_no
이의이 race_id
같은했다 car_type
. 각각에 대해 하나의 시퀀스 car_type
만 가질 수있는 한 더 간단하고 빠르며 정확합니다 race_id
.
그러나 간단한 쿼리 작업은 더 간단 할 수 있습니다. 논리적으로 lap_no
per 당 이 순서대로(car_type, race_id)
이루어져야하며 랩을 계산할 수 있습니다.
SELECT race_id, car_type, count(*) AS seq_len
FROM tbl
GROUP BY race_id, car_type
ORDER BY seq_len DESC
LIMIT 1;
반면에 race_id 당 여러 개의 개별 시퀀스를car_type
가질 수 있고 (질문이 달리 지정하지 않은 경우) Jack 버전이 실패합니다.
주어진 경주 / 자동차 유형에 대해 더 빠름
질문에서 주석 / 명확화 답장에서 님의 쿼리 제한 주어진 하나 (race_id, car_type)
를 만들 것입니다 훨씬 더 빨리 물론을 :
SELECT count(*) AS seq_len
FROM (
SELECT row_number() OVER (ORDER BY lap_no) - lap_no AS grp
FROM tbl
WHERE race_id = 1
AND car_type = 'red'
) x
GROUP BY grp
ORDER BY seq_len DESC
LIMIT 1;
db <> fiddle here
이전 SQL 바이올린
인덱스
최고 성능의 핵심은 적합 지수입니다 (단일 순차 스캔으로 작업하는 언급 된 절차 솔루션 제외). 이와 같은 다중 열 인덱스가 가장 적합합니다.
CREATE INDEX tbl_mult_idx ON tbl (race_id, car_type, lap_no);
테이블 UNIQUE
에 맨 위에 가정 한 제약 조건 이있는 경우 내부적 으로이 (고유 한) 인덱스로 구현되며 다른 인덱스를 만들 필요 가 없습니다 .