sql >> Databasteknik >  >> RDS >> Mysql

Luckor och öar på 2 kolumner - om kolumn A i följd och kolumn B är identiska

Det finns inte mycket att ändra i din fråga. Du måste i princip välja name och number i underfrågan och sortera i samma ordning. Sedan kan du gruppera efter name, number - rn i den yttre frågan.

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<>fiol

Jag brukar förespråka mot användningen av sessionsvariabler på detta sätt. Anledningen är att sådana lösningar är beroende av intern implementering och kan brytas av versionsuppdateringar eller inställningsändringar. Till exempel:När MariaDB bestämde sig för att ignorera ORDER BY-satsen i underfrågor utan LIMIT. Det är därför jag inkluderade en enorm LIMIT.

Jag ersatte också number med first_number i den yttre ORDER BY-satsen för att undvika problem med läget ONLY_FULL_GROUP_BY.

Ett mer stabilt sätt att generera radnummer är att använda en AOTO_INCREMENT-kolumn i en temporär tabell:

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 sista SELECT-frågan är identisk med den yttre frågan ovan:

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<>fiol

I en nyare version (med början från MariaDB 10.2) kan du använda ROW_NUMBER() fönsterfunktion istället:

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<>fiol



  1. SQL Server Massinsättning av CSV-fil med inkonsekventa citattecken

  2. Dra data från MySQL till json-arrayen

  3. MySQL-uppdatering ändra flera kolumner är icke-atomär?

  4. Databasen returnerade ett ogiltigt värde i QuerySet.dates()