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がLIMITなしのサブクエリでORDERBY句を無視することを決定した場合。これが、私が巨大な制限を含めた理由です。

    numberも置き換えました first_numberを使用 ONLY_FULL_GROUP_BYモードの問題を回避するために、外側のORDERBY句で。

    行番号を生成するためのより安定した方法は、一時テーブルで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. MariaDBで列のデータ型を確認する4つの方法

    2. MySQLは、Djangoの自動IDを使用して「フィールドリスト」エラーに不明な列「user.id」を表示します

    3. PostgreSQLで数値を含まない値を検索する

    4. リンクされたSQLサーバーのクエリ