Mô tả của bạn dẫn đến một định nghĩa bảng như thế này:
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)
);
Giải pháp chung cho lớp vấn đề này
Để có được chuỗi dài nhất (1 kết quả, dài nhất trong tất cả, chọn tùy ý nếu có quan hệ):
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)
chỉ tính TRUE
(= bước tới nhóm tiếp theo), dẫn đến một số mới cho mỗi nhóm mới.
Câu hỏi liên quan về SO, một câu trả lời có giải pháp thủ tục với plpgsql :
Nếu yêu cầu hàng đầu là hiệu năng, thì hàm plpgsql thường nhanh hơn trong trường hợp cụ thể này vì nó có thể tính kết quả trong một lần quét.
Nhanh hơn cho các số liên tiếp
Chúng ta có thể tận dụng thực tế là liên tiếp lap_no
xác định một chuỗi, cho phiên bản đơn giản hơn và nhanh hơn nhiều :
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;
Vòng đua liên tiếp kết thúc trong cùng grp
. Mỗi vòng thiếu kết quả trong một grp
phân vùng thấp hơn .
Điều này dựa trên (race_id, car_type, lap_no)
việc UNIQUE NOT NULL
. Giá trị NULL hoặc trùng lặp có thể phá vỡ logic.
Thảo luận về sự thay thế đơn giản hơn của Jack
@ Phiên bản của Jack hiệu quả đếm tất cả các vòng (hàng), nơi trước đó lap_no
trong này race_id
có giống nhau car_type
. Điều đó đơn giản hơn và nhanh hơn và chính xác - miễn là mỗi car_type
chỉ có thể có một chuỗi trên mỗi race_id
.
Nhưng đối với một nhiệm vụ đơn giản, truy vấn có thể đơn giản hơn. Nó sẽ tuân theo logic rằng tất cả lap_no
mỗi (car_type, race_id)
phải theo trình tự và chúng tôi chỉ có thể đếm các vòng:
SELECT race_id, car_type, count(*) AS seq_len
FROM tbl
GROUP BY race_id, car_type
ORDER BY seq_len DESC
LIMIT 1;
Mặt khác, nếu một người car_type
có thể có nhiều chuỗi riêng biệt cho mỗi racing_id (và câu hỏi không chỉ định khác), phiên bản của Jack sẽ thất bại.
Nhanh hơn cho một loại xe đua / xe nhất định
Trả lời nhận xét / làm rõ trong câu hỏi: hạn chế truy vấn cho một truy vấn nhất định(race_id, car_type)
sẽ làm cho nó nhanh hơn nhiều , tất nhiên:
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 ở đây Fiddle SQL
cũ
Mục lục
Chìa khóa để đạt hiệu suất cao nhất là một chỉ số phù hợp (ngoại trừ giải pháp thủ tục được đề cập làm việc với một lần quét tuần tự duy nhất). Một chỉ mục nhiều màu như thế này phục vụ tốt nhất:
CREATE INDEX tbl_mult_idx ON tbl (race_id, car_type, lap_no);
Nếu bảng của bạn có UNIQUE
ràng buộc mà tôi giả định ở trên cùng, điều đó được triển khai chỉ với chỉ mục (duy nhất) này trong nội bộ và bạn không cần tạo chỉ mục khác.