sql >> データベース >  >> RDS >> PostgreSQL

GROUPBYおよび集計連続数値

    連続していない値を特定することは常に少し注意が必要であり、いくつかのネストされたサブクエリが含まれます(少なくとも私はより良い解決策を思い付くことができません)。

    最初のステップは、その年の連続していない値を特定することです。

    ステップ1)連続していない値を特定する

    select company, 
           profession,
           year,
           case 
              when row_number() over (partition by company, profession order by year) = 1 or 
                   year - lag(year,1,year) over (partition by company, profession order by year) > 1 then 1
              else 0
           end as group_cnt
    from qualification
    

    これにより、次の結果が返されます。

     company | profession | year | group_cnt
    ---------+------------+------+-----------
     Google  | Programmer | 2000 |         1
     Google  | Sales      | 2000 |         1
     Google  | Sales      | 2001 |         0
     Google  | Sales      | 2002 |         0
     Google  | Sales      | 2004 |         1
     Mozilla | Sales      | 2002 |         1
    

    これで、group_cnt値を使用して、連続する年を持つ各グループの「グループID」を作成できます。

    ステップ2)グループIDを定義する

    select company,
       profession,
       year,
       sum(group_cnt) over (order by company, profession, year) as group_nr
    from ( 
    select company, 
           profession,
           year,
           case 
              when row_number() over (partition by company, profession order by year) = 1 or 
                   year - lag(year,1,year) over (partition by company, profession order by year) > 1 then 1
              else 0
           end as group_cnt
    from qualification
    ) t1
    

    これにより、次の結果が返されます。

     company | profession | year | group_nr
    ---------+------------+------+----------
     Google  | Programmer | 2000 |        1
     Google  | Sales      | 2000 |        2
     Google  | Sales      | 2001 |        2
     Google  | Sales      | 2002 |        2
     Google  | Sales      | 2004 |        3
     Mozilla | Sales      | 2002 |        4
    (6 rows)
    

    ご覧のとおり、各「グループ」には独自のgroup_nrがあり、これを使用して、さらに別の派生テーブルを追加することで、最終的に集計できます。

    ステップ3)最終クエリ

    select company,
           profession,
           array_agg(year) as years
    from (
      select company,
           profession,
           year,
           sum(group_cnt) over (order by company, profession, year) as group_nr
      from ( 
        select company, 
               profession,
               year,
               case 
                  when row_number() over (partition by company, profession order by year) = 1 or 
                       year - lag(year,1,year) over (partition by company, profession order by year) > 1 then 1
                  else 0
               end as group_cnt
        from qualification
      ) t1
    ) t2
    group by company, profession, group_nr
    order by company, profession, group_nr
    

    これにより、次の結果が返されます。

     company | profession |      years
    ---------+------------+------------------
     Google  | Programmer | {2000}
     Google  | Sales      | {2000,2001,2002}
     Google  | Sales      | {2004}
     Mozilla | Sales      | {2002}
    (4 rows)
    

    私が間違っていなければ、これはまさにあなたが望んでいたことです。



    1. 更新部分で新しい値と古い値の両方を使用できるようにUPSERTを実行する方法

    2. MySQLとは何ですか?

    3. マラソントレーニングアプリのデータモデル

    4. 1回の操作で複数のPostgreSQLテーブルのスキーマを変更するにはどうすればよいですか?