आपका विवरण इस तरह एक तालिका परिभाषा में परिणाम करता है :
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
(= अगले समूह के लिए कदम), जिसके परिणामस्वरूप हर नए समूह के लिए एक नई संख्या होती है।
एसओ पर संबंधित प्रश्न, एक जवाब जो 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
। पूर्ण मान या डुप्लिकेट तर्क तोड़ सकता है।
जैक के सरल विकल्प की चर्चा
@ जैक का संस्करण प्रभावी रूप से सभी अंतराल (पंक्तियों) को गिनाता है जहां पिछले 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, 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 <> यहाँ field
पुरानी SQL फ़ेल्ड
सूची
शीर्ष प्रदर्शन की कुंजी एक फिटिंग इंडेक्स है (एक एकल अनुक्रमिक स्कैन के साथ काम करने वाले उल्लिखित प्रक्रियात्मक समाधान को छोड़कर)। इस तरह का एक बहुरंगी सूचकांक सबसे अच्छा कार्य करता है:
CREATE INDEX tbl_mult_idx ON tbl (race_id, car_type, lap_no);
यदि आपकी तालिका में ऊपर की ओर UNIQUE
लगाई गई बाधा है, तो इसे केवल इस (अद्वितीय) सूचकांक के साथ आंतरिक रूप से लागू किया गया है, और आपको दूसरा सूचकांक बनाने की आवश्यकता नहीं है।