sql >> Databáze >  >> RDS >> Mysql

Mezery a ostrůvky na 2 sloupcích - pokud sloupec A po sobě jdoucí a sloupec B jsou totožné

Na vašem dotazu není moc co měnit. V zásadě musíte vybrat name a number v poddotazu a seřadit ve stejném pořadí. Poté můžete seskupit podle name, number - rn ve vnějším dotazu.

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;

Výsledek:

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

Obvykle obhajuji používání proměnných relace tímto způsobem. Důvodem je, že taková řešení závisí na interní implementaci a mohou být narušena aktualizacemi verzí nebo změnami nastavení. Například:Jakmile se MariaDB rozhodla ignorovat klauzuli ORDER BY v dílčích dotazech bez LIMIT. Proto jsem zahrnul obrovský LIMIT.

Také jsem nahradil number s first_number ve vnější klauzuli ORDER BY, abyste se vyhnuli problémům s režimem ONLY_FULL_GROUP_BY.

Stabilnějším způsobem generování čísel řádků je použití sloupce AOTO_INCREMENT v dočasné tabulce:

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;

Poslední dotaz SELECT je totožný s vnějším dotazem výše:

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

V novější verzi (počínaje MariaDB 10.2) můžete použít ROW_NUMBER() funkce okna místo toho:

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



  1. Uživatelské jméno, heslo, solení, šifrování, hash – jak to všechno funguje?

  2. Správa dat pomocí Pythonu, SQLite a SQLAlchemy

  3. Chyba připojení JDBC:nerozpoznané časové pásmo

  4. Perzistence připojení PHP MySQL