sql >> Database teknologi >  >> RDS >> Mysql

Mellemrum og øer på 2 kolonner - hvis kolonne A fortløbende og kolonne B er identiske

Der er ikke meget at ændre i din forespørgsel. Du skal grundlæggende vælge name og number i underforespørgslen og sorter i samme rækkefølge. Derefter kan du gruppere efter name, number - rn i den ydre forespørgsel.

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;

Resultat:

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
 

db<>fiddle

Jeg plejer at gå ind for brugen af ​​sessionsvariabler på denne måde. Årsagen er, at sådanne løsninger afhænger af intern implementering og kan brydes af versionsopdateringer eller indstillingsændringer. For eksempel:En gang besluttede MariaDB at ignorere ORDER BY-klausulen i underforespørgsler uden LIMIT. Det er derfor, jeg inkluderede en enorm LIMIT.

Jeg erstattede også number med first_number i den ydre ORDER BY-klausul for at undgå problemer med ONLY_FULL_GROUP_BY-tilstand.

En mere stabil måde at generere rækkenumre på er at bruge en AOTO_INCREMENT kolonne i en midlertidig tabel:

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;
 

Den endelige SELECT-forespørgsel er identisk med den ydre forespørgsel ovenfor:

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;
 

db<>violin

I en nyere version (startende fra MariaDB 10.2) kan du bruge ROW_NUMBER() vinduesfunktion i stedet:

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;

db<>violin



  1. Sådan sender du e-mail ved hjælp af Oracle 10 g Forms

  2. Sådan løses MySQL-fejl Du kan ikke angive måltabel X til opdatering i FROM-klausulen?

  3. Send AJAX-anmodning ved at klikke på et link uden at omdirigere brugeren

  4. MySQL indlæse data i fil - acceleration?