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

SQL ServerでのDENSE_RANK()のしくみ

    SQL Serverでは、DENSE_RANK() 関数は、結果セットのパーティション内の各行のランクを返します。行のランクは、1に、行の前にある個別のランクの数を加えたものです。

    この関数はRANK()に似ています 、ただし、RANK()で発生する可能性のあるランキング値のギャップはありません 結果セットに同点が存在する場合。

    構文

    構文は次のようになります:

    DENSE_RANK ( ) OVER ( [  ] < order_by_clause > )
    

    オプションです。 FROMによって生成された結果セットを分割します 関数が適用されるパーティションへの句。指定しない場合、クエリ結果セットのすべての行が単一のグループとして扱われます。

    必要とされている。関数がパーティション内の行に適用される順序を決定します。

    OVERに注意してください 句は通常、 を受け入れます 、ただし、その引数はこの関数では使用できません。

    例1-基本的な使用法

    DENSE_RANK()の使用法を示す基本的な例を次に示します。 機能:

    SELECT
      AlbumId,
      AlbumName,
      ArtistId,
      DENSE_RANK() OVER (ORDER BY ArtistId ASC) 'Rank'
    FROM Albums;
    

    結果:

    +-----------+--------------------------+------------+--------+
    | AlbumId   | AlbumName                | ArtistId   | Rank   |
    |-----------+--------------------------+------------+--------|
    | 1         | Powerslave               | 1          | 1      |
    | 7         | Somewhere in Time        | 1          | 1      |
    | 8         | Piece of Mind            | 1          | 1      |
    | 9         | Killers                  | 1          | 1      |
    | 10        | No Prayer for the Dying  | 1          | 1      |
    | 2         | Powerage                 | 2          | 2      |
    | 19        | All Night Wrong          | 3          | 3      |
    | 20        | The Sixteen Men of Tain  | 3          | 3      |
    | 12        | Big Swing Face           | 4          | 4      |
    | 4         | Ziltoid the Omniscient   | 5          | 5      |
    | 5         | Casualties of Cool       | 5          | 5      |
    | 6         | Epicloud                 | 5          | 5      |
    | 3         | Singing Down the Lane    | 6          | 6      |
    | 16        | Long Lost Suitcase       | 7          | 7      |
    | 17        | Praise and Blame         | 7          | 7      |
    | 18        | Along Came Jones         | 7          | 7      |
    | 11        | No Sound Without Silence | 9          | 8      |
    | 21        | Yo Wassup                | 9          | 8      |
    | 22        | Busted                   | 9          | 8      |
    | 13        | Blue Night               | 12         | 9      |
    | 14        | Eternity                 | 12         | 9      |
    | 15        | Scandinavia              | 12         | 9      |
    +-----------+--------------------------+------------+--------+
    

    ArtistId を見てください および ランク 列。 ArtistIdが増加するたびに、ランクが増加します。これは、ArtistIdで注文しているため、新しいアーティストごとに新しいランクが付けられるためです。

    結果はその列で並べ替えられるため、同じArtistIdを含む行の数に関係なく、ランクは各アーティストで同じままです。たとえば、5つの行には同じArtistIdが含まれているため、同じランクも含まれています。言い換えれば、それらはすべてランク1に結びついています。

    多くの行で、ランクはArtistIdと同じですが、これは単なる偶然です。 ArtistIdがIDENTITYであるのはたまたまです 1から始まり、1ずつ増加する列。これは、RANK()でもあります。 します。ただし、すべての行で同じではないことがわかります。たとえば、ArtistIdは7から9までスキップしますが、ランクは7から8まで単純に増加し、その時点から、両方の列に異なる値が含まれます。

    例2–パーティション

    結果をパーティションに分割することもできます。これを行うと、ランクは各パーティションに対して計算されます(したがって、新しいパーティションごとに最初からやり直します)。

    例:

    SELECT
      Genre,
      AlbumName,
      ArtistId,
      DENSE_RANK() OVER (PARTITION BY Genre ORDER BY ArtistId ASC) 'Rank'
    FROM Albums
    INNER JOIN Genres 
    ON Albums.GenreId = Genres.GenreId;
    

    結果:

    +---------+--------------------------+------------+--------+
    | Genre   | AlbumName                | ArtistId   | Rank   |
    |---------+--------------------------+------------+--------|
    | Country | Singing Down the Lane    | 6          | 1      |
    | Country | Yo Wassup                | 9          | 2      |
    | Country | Busted                   | 9          | 2      |
    | Jazz    | All Night Wrong          | 3          | 1      |
    | Jazz    | The Sixteen Men of Tain  | 3          | 1      |
    | Jazz    | Big Swing Face           | 4          | 2      |
    | Pop     | Long Lost Suitcase       | 7          | 1      |
    | Pop     | Praise and Blame         | 7          | 1      |
    | Pop     | Along Came Jones         | 7          | 1      |
    | Pop     | No Sound Without Silence | 9          | 2      |
    | Pop     | Blue Night               | 12         | 3      |
    | Pop     | Eternity                 | 12         | 3      |
    | Pop     | Scandinavia              | 12         | 3      |
    | Rock    | Powerslave               | 1          | 1      |
    | Rock    | Somewhere in Time        | 1          | 1      |
    | Rock    | Piece of Mind            | 1          | 1      |
    | Rock    | Killers                  | 1          | 1      |
    | Rock    | No Prayer for the Dying  | 1          | 1      |
    | Rock    | Powerage                 | 2          | 2      |
    | Rock    | Ziltoid the Omniscient   | 5          | 3      |
    | Rock    | Casualties of Cool       | 5          | 3      |
    | Rock    | Epicloud                 | 5          | 3      |
    +---------+--------------------------+------------+--------+
    

    この場合、ジャンル別に分割します。これにより、各行は同じパーティション内の他の行に対してのみランク付けされます。したがって、各パーティションにより、ランキング値は再び1から始まります。

    例3–スコアボードの例

    ユーザーにランクを表示するための考えられる使用例を次に示します。

    SELECT  
      Player,
      Score,
      DENSE_RANK() OVER (ORDER BY Score Desc) 'Rank'
    FROM Scoreboard;
    

    結果:

    +----------+---------+--------+
    | Player   | Score   | Rank   |
    |----------+---------+--------|
    | Bart     | 2010    | 1      |
    | Burns    | 1270    | 2      |
    | Meg      | 1030    | 3      |
    | Marge    | 990     | 4      |
    | Lisa     | 710     | 5      |
    | Ned      | 666     | 6      |
    | Apu      | 350     | 7      |
    | Homer    | 1       | 8      |
    +----------+---------+--------+
    

    同点の結果は後続のランクに影響を与えないことに注意してください。つまり、ランク値にギャップはありません。

    これはおそらく例で最もよく説明されます:

    SELECT  
      Player,
      Score,
      DENSE_RANK() OVER (ORDER BY Score Desc) 'Rank'
    FROM Scoreboard;
    

    結果:

    +----------+---------+--------+
    | Player   | Score   | Rank   |
    |----------+---------+--------|
    | Lisa     | 2010    | 1      |
    | Bart     | 2010    | 1      |
    | Burns    | 1270    | 2      |
    | Meg      | 1030    | 3      |
    | Marge    | 990     | 4      |
    | Ned      | 666     | 5      |
    | Apu      | 350     | 6      |
    | Homer    | 1       | 7      |
    +----------+---------+--------+
    

    この場合、リサとバートは1番で同点になります。その後、バーンズは2番で入ります(彼は3人目ですが)。

    この場合、Burnsが3位(およびMegが4位など)にランク付けされることを希望する場合は、RANK()を使用してください。 代わりに機能します。

    例4– DENSE_RANK()をRANK()に置き換える

    今回もRANK()を使用することを除いて、同じ例を次に示します。 :

    SELECT  
      Player,
      Score,
      RANK() OVER (ORDER BY Score Desc) 'Rank'
    FROM Scoreboard;
    

    結果:

    +----------+---------+--------+
    | Player   | Score   | Rank   |
    |----------+---------+--------|
    | Lisa     | 2010    | 1      |
    | Bart     | 2010    | 1      |
    | Burns    | 1270    | 3      |
    | Meg      | 1030    | 4      |
    | Marge    | 990     | 5      |
    | Ned      | 666     | 6      |
    | Apu      | 350     | 7      |
    | Homer    | 1       | 8      |
    +----------+---------+--------+
    

    1. 現在の日付が2つの日付の間にあるかどうかを確認しますOracleSQL

    2. SQL Server-トランザクションはエラー時にロールバックしますか?

    3. SQL Server(T-SQL)で日付から月を抽出する3つの方法

    4. 別のテーブルのフィールドから1つのテーブルのSQL更新フィールド