Không có nhiều thay đổi trong truy vấn của bạn. Về cơ bản, bạn cần chọn name
và number
trong truy vấn con và sắp xếp theo cùng một thứ tự. Sau đó, bạn có thể nhóm theo name, number - rn
trong truy vấn bên ngoài.
SELECT
min(number) first_number,
max(number) last_number,
count(*) AS no_records,
name
FROM (
SELECT c.*, @rn := @rn + 1 rn
from (
SELECT name, number
FROM `table`
WHERE cc = 1
ORDER BY name, number
LIMIT 99999999999999999
) AS c
CROSS JOIN (SELECT @rn := 0) r
) c
GROUP BY name, number - rn
ORDER BY first_number ASC, name ASC;
Kết quả:
first_number last_number no_records name
1 2 2 Apple
3 3 1 Bean
10 12 3 Hello
14 14 1 Deer
14 14 1 Door
15 15 1 Hello
17 17 1 Hello
Tôi thường ủng hộ việc chống lại việc sử dụng các biến phiên theo cách này. Lý do là các giải pháp như vậy phụ thuộc vào việc triển khai nội bộ và có thể bị phá vỡ bởi các bản cập nhật phiên bản hoặc thay đổi cài đặt. Ví dụ:Khi MariaDB quyết định bỏ qua mệnh đề ORDER BY trong các truy vấn con mà không có LIMIT. Đây là lý do tại sao tôi bao gồm một LIMIT rất lớn.
Tôi cũng đã thay thế number
với first_number
trong mệnh đề ORDER BY bên ngoài để tránh sự cố với chế độ ONLY_FULL_GROUP_BY.
Một cách ổn định hơn để tạo số hàng là sử dụng cột AOTO_INCREMENT trong bảng tạm thời:
drop temporary table if exists tmp_tbl;
create temporary table tmp_tbl (
rn int unsigned auto_increment primary key,
name varchar(64) not null,
number int not null
);
insert into tmp_tbl (name, number)
select name, number
from `table`
order by name, number;
Truy vấn SELECT cuối cùng giống với truy vấn bên ngoài ở trên:
SELECT
min(number) first_number,
max(number) last_number,
count(*) AS no_records,
name
FROM tmp_tbl
GROUP BY name, number - rn
ORDER BY first_number ASC, name ASC;
Trong phiên bản mới hơn (bắt đầu từ MariaDB 10.2), bạn có thể sử dụng ROW_NUMBER()
chức năng cửa sổ thay thế:
SELECT
min(number) first_number,
max(number) last_number,
count(*) AS no_records,
name
FROM (
SELECT
name,
number,
row_number() OVER (ORDER BY name, number) as rn
FROM `table`
WHERE cc = 1
) c
GROUP BY name, number - rn
ORDER BY first_number ASC, name ASC;