2012-05-07 11 views
32

私は他の誰かによって書かれたSQLクエリーを持っており、それが何であるか把握しようとしています。誰かがPartition ByRow_Numberというキーワードがここで何をしているのかを説明し、実際の使用例とその理由を説明してください。Oracleの「Partition By」および「Row_Number」キーワード

によってパーティションの例:私はオンラインいくつかの例を見てきました

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

、彼らは少しも深さです。

ありがとうございます!

答えて

89

PARTITION BY分離セットが、これは独立して、関連セットに(ROW_NUMBER()、COUNT()、SUM()など)あなたが働くことができるようになります。

関連するセットは、類似のcdt.country_code、cdt.account、cdt.currencyを持つ行で構成されています。これらの列でパーティションを作成し、その列にROW_NUMBERを適用します。それらの組み合わせ/セットの他の列は、ROW_NUMBERから連続番号を受け取ります

しかし、このクエリは面白いです。パーティションがいくつかの一意のデータで、row_numberを置くと同じ数になります。一意であることが保証されているパーティションでORDER BYを実行するようなものです。 GUIDは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

に設定されている基本的に、あなたは非ユニークに分割する必要があります(いずれもすべての行が、自分の行に分割され、分割されませんでした)列。そして、これはあなたのクエリに似ている

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'); 

:OVERにORDER BYがそうでなければ、すべてのrow_numbersが1

例になるだろう、非ユニークな組み合わせを持っているのPARTITION BYが必要、これはあなたのデータであり、

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を持ち、HI C行と同様にROW_NUMBERSが異なります。

ここで、ORDER BYはなぜ必要なのですか?

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

しかし、悲しいかな、(余りにおよびSQL Server)は、Oracleのdoesn:以前の開発者は、単に同様のデータにROW_NUMBERを入れたい場合(例えばHI B、全てのデータがBW、BWある)、彼はちょうどこれを行うことができますパーティションを許可しないでください。ORDER BY; PostgreSQLでは、PARTITIONのORDER BYがオプションであるのに対し:http://www.sqlfiddle.com/#!1/27821/1

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

あなたのパーティション上のORDER BYがないため、以前の開発者のせいで、冗長ビットを見て、いくつかのデータベースだけでなしORDER BYPARTITIONを許可していない、彼は可能性があります並べ替えるための良い候補列を見つけることができません。 BY列列とORDER BYの両方のパーティションが同じである場合だけで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を使用できます(SQL Serverの場合はnewid()を使用します)。以前の開発者が同じ出力をしているので、一部のデータベースでは許可されていないのは残念ですPARTITIONORDER BY

実際には、 BW、BW)。それは冗長データを持つデータベースの印象を与えています。何らかの形でこのことを私に思い出させました:How to get one unique record from the same list of records from table? No Unique constraint in the table

ORDER BYと同じ列の組み合わせでPARTITION BYを見ると、実際にはコードの意図を推測できません。

ライブテスト: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'); 

次にあなたがして、パーティションホ、ハイテク;そして、あなたは、こんにちは、頼むよ。

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 

参照してください: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; 

出力:-)同様のデータを番号付けても意味はありませんか?同じ組み合わせに行番号を付ける必要があるのはなぜですか?ダブルC、ZでダブルB、YでトリプルA、Xで分析するものは? :-)


あなたは、あなたのソート非一意な列(複数可)のユニーク -ing列に、非一意な列にPARTITIONを使用する必要があります。例には、それがより明確になります。

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あなたは、そのユニークなコラム(ホ)に注文し、各パーティションの列に、非一意な列上で動作し、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

そして、これはBYの両方BY PARTITIONとORDER上の同じ列を持つクエリに似ています。

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 
7

これは、国番号、口座、および通貨ごとの行番号を選択します。したがって、国コード「US」、口座「XYZ」、通貨「$ USD」の行は、それぞれ1-nから割り当てられた行番号を取得します。結果セット内のこれらの列の組み合わせごとに同じことが行われます。

句の順序は絶対に何もないので、このクエリは面白いです。各パーティションのすべての行には同じ国コード、勘定、通貨が設定されているため、これらの列でポイント順はありません。したがって、この特定のクエリで割り当てられる最終行番号は予測できません。助け

希望...

4

は、私は頻繁に私のSELECTステートメントから重複レコードを破棄する簡単な方法として、ROW_NUMBER()を使用します。 where句を追加するだけです。以下のような何か...

select a,b,rn 
    from (select a, b, row_number() over (partition by a,b order by a,b) as rn   
      from table) 
where rn=1; 
2

私は、これは古いスレッドですが、PARTITIONは、ORDER BY、GROUP BYないの当量であることを知っています。この関数のORDER BYはです。 。 。 ORDER BY。これは、シーケンス番号を追加することで冗長性から一意性を作り出す単なる方法です。または、関数のエイリアス化された列を参照するときに、WHERE句で他の冗長レコードを削除することもできます。しかし、SELECT文の中のDISTINCTは、おそらく同じ点を達成するでしょう。

関連する問題