Tôi đã thử nó theo các cách khác nhau và hiệu suất tốt nhất mà tôi tìm thấy là truy vấn đơn giản sau:
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
;
... một phép nối bên trái để kiểm tra xem id tiếp theo có tồn tại hay không, chỉ khi tiếp theo nếu không được tìm thấy, sau đó truy vấn con tìm id tiếp theo tồn tại để tìm cuối khoảng trống. Tôi đã làm điều đó vì truy vấn với bằng (=) có hiệu suất tốt hơn toán tử lớn hơn (>).
Sử dụng sqlfiddle, nó không hiển thị quá khác biệt so với các truy vấn khác nhưng trong cơ sở dữ liệu thực, truy vấn trên cho kết quả nhanh hơn 3 lần so với các truy vấn khác.
Lược đồ:
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)
;
Thực hiện theo tất cả các truy vấn mà tôi đã thực hiện để so sánh hiệu suất:
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
;
Có thể nó sẽ giúp ích cho ai đó và hữu ích.
Bạn có thể xem và kiểm tra truy vấn của tôi bằng sqlfiddle này :
http://sqlfiddle.com/#!9/6bdca7/1