Mysql
 sql >> база данни >  >> RDS >> Mysql

Пропуски и острови на 2 колони - ако колона A е последователна и колона B са идентични

Няма много за промяна във вашата заявка. По принцип трябва да изберете name и number в подзаявката и сортирайте в същия ред. След това можете да групирате по name, number - rn във външната заявка.

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;

Резултат:

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

Обикновено се застъпвам срещу използването на променливи на сесията по този начин. Причината е, че подобни решения зависят от вътрешната реализация и могат да бъдат нарушени от актуализации на версиите или промени в настройките. Например:След като MariaDB реши да игнорира клаузата ORDER BY в подзаявки без LIMIT. Ето защо включих огромен LIMIT.

Замених също number с first_number във външната клауза ORDER BY, за да избегнете проблеми с режима ONLY_FULL_GROUP_BY.

По-стабилен начин за генериране на номера на редове е да използвате колона AOTO_INCREMENT във временна таблица:

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;

Последната заявка SELECT е идентична с външната заявка по-горе:

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

В по-нова версия (започвайки от MariaDB 10.2) можете да използвате ROW_NUMBER() функция прозорец вместо това:

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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. как да добавя нова колона всеки път, когато стартирам програма на python

  2. Много специфична MySQL заявка, която искам да подобря

  3. Как да получите идентификатор на ред в mysql

  4. mysql 12 часа в 24 часа преобразуване на времето

  5. Как да свържа приложението за Android към базата данни MySQL?