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

Oracleの「PartitionBy」および「Row_Number」キーワード

    PARTITION BY セットを分離します。これにより、関連するセットで独立して作業(ROW_NUMBER()、COUNT()、SUM()など)できるようになります。

    クエリでは、関連するセットは、類似したcdt.country_code、cdt.account、cdt.currencyの行で構成されています。それらの列を分割し、それらにROW_NUMBERを適用する場合。それらの組み合わせ/セットの他の列は、ROW_NUMBER

    から連番を受け取ります。

    しかし、そのクエリはおかしいです。いくつかの一意のデータによるパーティションで、row_numberをその上に置くと、同じ番号が生成されます。これは、一意であることが保証されているパーティションでORDERBYを実行するようなものです。たとえば、GUIDをcdt.country_code, cdt.account, cdt.currencyの一意の組み合わせと考えてください。

    newid() GUIDを生成するので、この式で何を期待しますか?

    select
       hi,ho,
       row_number() over(partition by newid() order by hi,ho)
    from tbl;
    

    ...そうです、すべてのパーティション化された(パーティション化されていない、すべての行が独自の行にパーティション化されている)行のrow_numbersはすべて1に設定されています

    基本的に、一意でない列でパーティション化する必要があります。 ORDER BY on OVERでは、PARTITION BYを一意でない組み合わせにする必要がありました。そうしないと、すべてのrow_numbersが1になります

    例:これはあなたのデータです:

    create table tbl(hi varchar, ho varchar);
    
    insert into tbl values
    ('A','X'),
    ('A','Y'),
    ('A','Z'),
    ('B','W'),
    ('B','W'),
    ('C','L'),
    ('C','L');
    

    次に、これはクエリに類似しています:

    select
       hi,ho,
       row_number() over(partition by hi,ho order by hi,ho)
    from tbl;
    

    その出力はどうなりますか?

    HI  HO  COLUMN_2
    A   X   1
    A   Y   1
    A   Z   1
    B   W   1
    B   W   2
    C   L   1
    C   L   2
    

    HI HOの組み合わせが見えますか?最初の3行は一意の組み合わせであるため、1に設定され、B行のWは同じであるため、HIC行と同様にROW_NUMBERSが異なります。

    では、なぜORDER BYなのですか? そこに必要ですか?前の開発者が単に類似したデータにrow_numberを配置したい場合(たとえば、HI B、すべてのデータはB-W、B-W)、彼はこれを行うことができます:

    select
       hi,ho,
       row_number() over(partition by hi,ho)
    from tbl;
    

    しかし、残念ながら、Oracle(およびSQL Serverも)はORDER BYのないパーティションを許可していません;一方、Postgresqlでは、ORDER BY on PARTITIONはオプションです:http://www.sqlfiddle.com/#!1/27821/1

    select
       hi,ho,
       row_number() over(partition by hi,ho)
    from tbl;
    

    ORDER BY 以前の開発者のせいではなく、パーティション上で少し冗長に見えます。一部のデータベースでは、PARTITIONが許可されていません。 ORDER BYなし 、並べ替えるのに適した候補列が見つからない可能性があります。 PARTITIONBY列とORDERBY列の両方が同じである場合は、ORDER BYを削除するだけですが、一部のデータベースでは許可されていないため、次のようにすることができます。

    SELECT cdt.*,
            ROW_NUMBER ()
            OVER (PARTITION BY cdt.country_code, cdt.account, cdt.currency
                  ORDER BY newid())
               seq_no
       FROM CUSTOMER_DETAILS cdt
    

    類似データの並べ替えに使用するのに適した列が見つかりませんか?ランダムに並べ替えた方がよいでしょう。パーティション化されたデータは同じ値を持っています とりあえず。たとえば、GUIDを使用できます(newid()を使用します SQL Serverの場合)。以前の開発者による出力と同じであるため、一部のデータベースでPARTITIONが許可されていないのは残念です。 ORDER BYなし

    本当に、それは私にはわかりません、そして私は同じ組み合わせ(上記の例ではB-W、B-W)に番号を付ける正当な理由を見つけることができません。データベースに冗長なデータがあるような印象を与えます。どういうわけか私にこれを思い出させました:テーブルからのレコードの同じリストから1つのユニークなレコードを取得する方法は?テーブルに一意性制約はありません

    ORDERBYと同じ列の組み合わせを持つPARTITIONBYを見ると、本当に難解に見えますが、コードの意図を簡単に推測することはできません。

    ライブテスト:http://www.sqlfiddle.com/#!3/27821/6

    しかし、dbasemanも気付いたように、同じ列でパーティションを作成して並べ替えるのは無意味です。

    次のようなデータセットがあります:

    create table tbl(hi varchar, ho varchar);
    
    insert into tbl values
    ('A','X'),
    ('A','X'),
    ('A','X'),
    ('B','Y'),
    ('B','Y'),
    ('C','Z'),
    ('C','Z');
    

    次に、こんにちは、hoでパーティションを作成します。それからあなたはこんにちは、hoで注文します。同様のデータに番号を付ける意味はありません:-)http://www.sqlfiddle.com/#!3/29ab8/3

    select
       hi,ho,
       row_number() over(partition by hi,ho order by hi,ho) as nr
    from tbl;
    

    出力:

    HI  HO  ROW_QUERY_A
    A   X   1
    A   X   2
    A   X   3
    B   Y   1
    B   Y   2
    C   Z   1
    C   Z   2
    

    見る?なぜ同じ組み合わせに行番号を付ける必要があるのですか?トリプルA、X、ダブルB、Y、ダブルC、Zで何を分析しますか? :-)

    一意でない列でPARTITIONを使用するだけで、一意でない列の一意ので並べ替えることができます。 -ing列。例でより明確になります:

    create table tbl(hi varchar, ho varchar);
    
    insert into tbl values
    ('A','D'),
    ('A','E'),
    ('A','F'),
    ('B','F'),
    ('B','E'),
    ('C','E'),
    ('C','D');
    
    select
       hi,ho,
       row_number() over(partition by hi order by ho) as nr
    from tbl;
    

    PARTITION BY hi 非一意の列で動作し、次にパーティション化された各列で、その一意の列(ho)、ORDER BY hoで注文します

    出力:

    HI  HO  NR
    A   D   1
    A   E   2
    A   F   3
    B   E   1
    B   F   2
    C   D   1
    C   E   2
    

    そのデータセットの方が理にかなっています

    ライブテスト:http://www.sqlfiddle.com/#!3 / d0b44 / 1

    これは、PARTITIONBYとORDERBYの両方に同じ列があるクエリに似ています:

    select
       hi,ho,
       row_number() over(partition by hi,ho order by hi,ho) as nr
    from tbl;
    

    そしてこれが出力です:

    HI  HO  NR
    A   D   1
    A   E   1
    A   F   1
    B   E   1
    B   F   1
    C   D   1
    C   E   1
    

    見る?意味がありませんか?

    ライブテスト:http://www.sqlfiddle.com/#!3 / d0b44 / 3

    最後に、これは正しいクエリかもしれません:

    SELECT cdt.*,
         ROW_NUMBER ()
         OVER (PARTITION BY cdt.country_code, cdt.account -- removed: cdt.currency
               ORDER BY 
                   -- removed: cdt.country_code, cdt.account, 
                   cdt.currency) -- keep
            seq_no
    FROM CUSTOMER_DETAILS cdt
    


    1. ResultSetを返す

    2. Oracle PL/SQLをPostgresqlPL/pgSQLに変換するためのツール

    3. PASSサミット2013:シャーロットでの成功

    4. 配列をMySQLストアドルーチンに渡す