Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Celah dan pulau pada 2 kolom - jika kolom A berurutan dan kolom B identik

Tidak banyak yang berubah dalam kueri Anda. Anda pada dasarnya perlu memilih name dan number dalam subquery dan mengurutkan dalam urutan yang sama. Kemudian Anda dapat mengelompokkan berdasarkan name, number - rn di kueri luar.

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;

Hasil:

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

Saya biasanya menganjurkan penggunaan variabel sesi dengan cara ini. Alasannya adalah bahwa solusi tersebut bergantung pada implementasi internal, dan dapat dipatahkan oleh pembaruan versi atau perubahan pengaturan. Misalnya:Setelah MariaDB memutuskan untuk mengabaikan klausa ORDER BY dalam subkueri tanpa LIMIT. Inilah mengapa saya menyertakan LIMIT yang sangat besar.

Saya juga mengganti number dengan first_number di bagian luar klausa ORDER BY untuk menghindari masalah dengan mode ONLY_FULL_GROUP_BY.

Cara yang lebih stabil untuk menghasilkan nomor baris adalah dengan menggunakan kolom AOTO_INCREMENT di tabel sementara:

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;

Kueri SELECT terakhir identik dengan kueri luar di atas:

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

Dalam versi yang lebih baru (mulai dari MariaDB 10.2) Anda dapat menggunakan ROW_NUMBER() fungsi jendela sebagai gantinya:

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



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Mysql:Menampilkan nilai kolom di bawah kolom lain

  2. com.mysql.jdbc.exceptions.jdbc4.CommunicationsException:Kegagalan tautan komunikasi ke basis data jarak jauh

  3. Bagaimana cara mengetahui apakah suatu tanggal cocok dengan interval di PHP atau MySQL?

  4. 193:%1 bukan bug aplikasi Win32 yang valid dengan Aplikasi Rails baru

  5. Ganti di MySQL