Il n'y a pas grand chose à changer dans votre requête. Vous devez essentiellement sélectionner name
et number
dans la sous-requête et trier dans le même ordre. Ensuite, vous pouvez grouper par name, number - rn
dans la requête externe.
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;
Résultat :
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
Je préconise généralement contre l'utilisation des variables de session de cette manière. La raison en est que ces solutions dépendent de la mise en œuvre interne et peuvent être interrompues par des mises à jour de version ou des modifications de paramètres. Par exemple :Une fois que MariaDB a décidé d'ignorer la clause ORDER BY dans les sous-requêtes sans LIMIT. C'est pourquoi j'ai inclus une énorme LIMITE.
J'ai aussi remplacé number
avec first_number
dans la clause ORDER BY externe pour éviter les problèmes avec le mode ONLY_FULL_GROUP_BY.
Une manière plus stable de générer des numéros de lignes consiste à utiliser une colonne AOTO_INCREMENT dans une table temporaire :
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;
La requête SELECT finale est identique à la requête externe ci-dessus :
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;
Dans une version plus récente (à partir de MariaDB 10.2), vous pouvez utiliser ROW_NUMBER()
fonction de fenêtre à la place :
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;