Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Szczeliny i wyspy na 2 kolumnach - jeśli kolumna A jest następna, a kolumna B identyczna

W zapytaniu nie ma wiele do zmiany. Zasadniczo musisz wybrać name i number w podzapytaniu i sortuj w tej samej kolejności. Następnie możesz grupować według name, number - rn w zewnętrznym zapytaniu.

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;

Wynik:

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

Zwykle opowiadam się przeciwko używaniu zmiennych sesji w ten sposób. Powodem jest to, że takie rozwiązania zależą od wewnętrznej implementacji i mogą zostać zepsute przez aktualizacje wersji lub zmiany ustawień. Na przykład:Kiedy MariaDB zdecydowała się zignorować klauzulę ORDER BY w podzapytaniach bez LIMIT. Dlatego dodałem ogromny LIMIT.

Zamieniłem również number z first_number w zewnętrznej klauzuli ORDER BY, aby uniknąć problemów z trybem ONLY_FULL_GROUP_BY.

Bardziej stabilnym sposobem generowania numerów wierszy jest użycie kolumny AOTO_INCREMENT w tabeli tymczasowej:

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;

Ostateczne zapytanie SELECT jest identyczne z zapytaniem zewnętrznym powyżej:

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

W nowszej wersji (począwszy od MariaDB 10.2) możesz użyć ROW_NUMBER() zamiast tego funkcja okna:

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



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Perl:Zaktualizuj wiele wierszy za pomocą jednego wywołania MySQL

  2. Oblicz deltę (różnicę bieżącego i poprzedniego wiersza) grupę mysql według określonej kolumny

  3. Logika warunków WHERE AND/OR w MySQL wielokrotna

  4. MySQLNonTransientConnectionException:Nie można utworzyć połączenia z serwerem bazy danych

  5. W jaki sposób MySQL określa, kiedy pokazywać jawne wartości zestawu znaków i sortowania?