sql >> Database >  >> RDS >> Mysql

Hiaten en eilanden op 2 kolommen - als kolom A opeenvolgend en kolom B identiek is

Er verandert niet veel aan uw zoekopdracht. U moet in principe name selecteren en number in de subquery en sorteer in dezelfde volgorde. Dan kun je groeperen op name, number - rn in de buitenste vraag.

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;

Resultaat:

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

Ik pleit meestal tegen het gebruik van sessievariabelen op deze manier. De reden is dat dergelijke oplossingen afhankelijk zijn van interne implementatie en kunnen worden verbroken door versie-updates of instellingenwijzigingen. Bijvoorbeeld:zodra MariaDB besloot om de ORDER BY-clausule in subquery's zonder LIMIT te negeren. Daarom heb ik een enorme LIMIET opgenomen.

Ik heb ook number vervangen met first_number in de buitenste ORDER BY-clausule om problemen met de ONLY_FULL_GROUP_BY-modus te voorkomen.

Een stabielere manier om rijnummers te genereren, is door een AOTO_INCREMENT-kolom in een tijdelijke tabel te gebruiken:

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;

De laatste SELECT-query is identiek aan de buitenste query hierboven:

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

In een recentere versie (vanaf MariaDB 10.2) kunt u ROW_NUMBER() gebruiken vensterfunctie in plaats daarvan:

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



  1. NULL vervangen door een andere waarde in SQL Server - ISNULL()

  2. Impact van de query_post_execution_showplan Extended Event in SQL Server 2012

  3. MySQL XDevAPI Een succesvolle status retourneren

  4. Hoe te bestellen op datum in PostgreSQL of Oracle