คำอธิบายของคุณส่งผลให้คำจำกัดความของตารางเช่นนี้:
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 หรือรายการซ้ำอาจทำให้ลอจิกแตก
การอภิปรายของทางเลือกที่ง่ายกว่าของแจ็ค
@ รุ่นแจ็คได้อย่างมีประสิทธิภาพนับทุกรอบ (แถว) ที่ก่อนหน้าlap_no
นี้ได้เหมือนกันrace_id
car_type
นั่นคือเรียบง่ายและเร็วขึ้นและถูกต้อง - ตราบใดที่แต่ละอันcar_type
สามารถมีลำดับเดียวrace_id
ได้
แต่สำหรับงานที่ง่ายแบบสอบถามอาจจะง่ายกว่านี้ มันจะเป็นไปตามเหตุผลว่าทั้งหมดlap_no
ต่อ(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;
หากในอีกด้านหนึ่งcar_type
สามารถมีหลายลำดับแยกกันต่อrace_id (และคำถามไม่ได้ระบุเป็นอย่างอื่น) รุ่นของแจ็คจะล้มเหลว
เร็วขึ้นสำหรับประเภทการแข่งขัน / รถยนต์ที่ระบุ
ในการตอบความเห็น / ชี้แจงในคำถาม: การ จำกัด แบบสอบถามไปยังหนึ่งที่ได้รับ (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 ที่นี่
Old SQL Fiddle
ดัชนี
ประสิทธิภาพการทำงานของ Key to top เป็นดัชนีที่เหมาะสม (ยกเว้นโซลูชันขั้นตอนที่กล่าวถึงซึ่งทำงานด้วยการสแกนตามลำดับครั้งเดียว) ดัชนีหลายคอลัมน์เช่นนี้ให้บริการอาหารที่ดีที่สุด:
CREATE INDEX tbl_mult_idx ON tbl (race_id, car_type, lap_no);
หากตารางของคุณมีUNIQUE
ข้อ จำกัด ที่ฉันสันนิษฐานว่าอยู่ด้านบนนั่นจะถูกนำมาใช้กับดัชนี (เฉพาะ) นี้ภายในและคุณไม่จำเป็นต้องสร้างดัชนีอื่น