I próbował go w różny sposób i najlepszej wydajności, które znalazłem było to proste zapytanie:
select a.id+1 gapIni
,(select x.id-1 from arrc_vouchers x where x.id>a.id+1 limit 1) gapEnd
from arrc_vouchers a
left join arrc_vouchers b on b.id=a.id+1
where b.id is null
order by 1
;
... jedno lewe sprzężenie, aby sprawdzić, czy następny identyfikator istnieje, tylko jeśli następne, jeśli nie zostanie znalezione, wówczas podzapytanie znajduje następny identyfikator, który istnieje, aby znaleźć koniec przerwy. Zrobiłem to, ponieważ zapytanie z równością (=) ma lepszą wydajność niż operator większy niż (>).
Korzystanie z sqlfiddle nie pokazuje tak różnej wydajności innych zapytań, ale w prawdziwej bazie danych powyższe zapytanie daje 3 razy szybszy wynik niż inne.
Schemat:
CREATE TABLE arrc_vouchers (id int primary key)
;
INSERT INTO `arrc_vouchers` (`id`) VALUES (1),(4),(5),(7),(8),(9),(10),(11),(15),(16),(17),(18),(19),(20),(21),(22),(23),(24),(25),(26),(27),(28),(29)
;
Wykonaj poniżej wszystkie zapytania, które wykonałem, aby porównać wydajność:
select a.id+1 gapIni
,(select x.id-1 from arrc_vouchers x where x.id>a.id+1 limit 1) gapEnd
from arrc_vouchers a
left join arrc_vouchers b on b.id=a.id+1
where b.id is null
order by 1
;
select *, (gapEnd-gapIni) qt
from (
select id+1 gapIni
,(select x.id from arrc_vouchers x where x.id>a.id limit 1) gapEnd
from arrc_vouchers a
order by id
) a where gapEnd <> gapIni
;
select id+1 gapIni
,(select x.id from arrc_vouchers x where x.id>a.id limit 1) gapEnd
#,coalesce((select id from arrc_vouchers x where x.id=a.id+1),(select x.id from arrc_vouchers x where x.id>a.id limit 1)) gapEnd
from arrc_vouchers a
where id+1 <> (select x.id from arrc_vouchers x where x.id>a.id limit 1)
order by id
;
select id+1 gapIni
,coalesce((select id from arrc_vouchers x where x.id=a.id+1),(select x.id from arrc_vouchers x where x.id>a.id limit 1)) gapEnd
from arrc_vouchers a
order by id
;
select id+1 gapIni
,coalesce((select id from arrc_vouchers x where x.id=a.id+1),concat('*** GAT *** ',(select x.id from arrc_vouchers x where x.id>a.id limit 1))) gapEnd
from arrc_vouchers a
order by id
;
Może to komuś pomoże i przydatne.
Możesz zobaczyć i przetestować moje zapytanie za pomocą tego sqlfiddle :
http://sqlfiddle.com/#!9/6bdca7/1