Açıklamanız şöyle bir tablo tanımıyla sonuçlanır :
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)
);
Bu sorun sınıfı için genel çözüm
En uzun sekansı elde etmek için (1 sonuç, en uzun, bağlar varsa keyfi seçim):
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)
sadece TRUE
her yeni grup için yeni bir sayı ile sonuçlanan (= sonraki gruba adım) sayar .
Pl ile ilgili soru, plpgsql ile prosedürel bir çözüm içeren bir cevap :
En yüksek gereksinim performanssa, plpgsql işlevi bu özel durumda genellikle daha hızlıdır çünkü sonucu tek bir taramada hesaplayabilir.
Ardışık sayılar için daha hızlı
Çok daha basit ve daha hızlı bir sürüm için ardışık lap_no
bir sekans tanımlaması gerçeğinden yararlanabiliriz :
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;
Ardışık turlar da aynı şekilde sonuçlanır grp
. Eksik olan her tur, grp
bölüm başına daha düşük bir sonuç verir .
Bu (race_id, car_type, lap_no)
varlığa dayanır UNIQUE NOT NULL
. NULL değerler veya kopyalar mantığı bozabilir.
Jack'in daha basit alternatifinin tartışılması
Jack'in versiyonu @ etkili tüm tur (satırlar) sayar önceki nereye lap_no
bunda race_id
aynı vardı car_type
. Bu daha basit ve daha hızlı ve doğrudur - her biri car_type
sadece bir sıraya sahip olabildiği sürece race_id
.
Ancak bu kadar basit bir görev için, sorgu henüz daha basit olabilir. Hepsi mantıksal olarak takip edecek lap_no
başına (car_type, race_id)
olmalıdır sırayla ve biz sadece tur güvenebileceğimi:
SELECT race_id, car_type, count(*) AS seq_len
FROM tbl
GROUP BY race_id, car_type
ORDER BY seq_len DESC
LIMIT 1;
Öte yandan, tek Eğer car_type
olabilir birden fazla ayrı dizileri başına race_id (ve soru aksi belirtmez), Jack'in versiyonu başarısız olur.
Belirli bir yarış / araba tipi için daha hızlı
Sorudaki açıklamaya / açıklamalara cevap olarak: sorguyu belirli bir soruyla sınırlamak elbette çok daha hızlı(race_id, car_type)
hale getirecektir :
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 <> keman burada
Eski SQL Keman
indeks
En üst düzeyde performans bir uyum indeksidir (tek bir ardışık tarama ile çalışan söz konusu prosedür çözümü hariç). Bunun gibi çok sütunlu bir dizin en iyi sonucu verir:
CREATE INDEX tbl_mult_idx ON tbl (race_id, car_type, lap_no);
Masanız varsa UNIQUE
kısıtlamayı içeriden sadece bu (benzersiz) endeksi ile uygulanan üstündeki varsayılır ve do not başka bir dizin oluşturmanız gerekir.