PARTITION BY
セットを分離します。これにより、関連するセットで独立して作業 (ROW_NUMBER()、COUNT()、SUM() など) できるようになります。
クエリでは、cdt.country_code、cdt.account、cdt.currency が類似する行で構成される関連セット。これらの列をパーティション分割し、それらに ROW_NUMBER を適用する場合。これらの組み合わせ/セットの他の列には、ROW_NUMBER から連番が割り当てられます
しかし、そのクエリは面白いです。いくつかの一意のデータでパーティションを分割し、それに row_number を配置すると、同じ番号が生成されます。一意であることが保証されているパーティションで ORDER BY を実行するようなものです。例、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 に設定されています
基本的に、一意でない列でパーティション化する必要があります。OVER の ORDER BY では、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 は同じであるため、ROW_NUMBERS が異なります。HI C 行と同様です。
では、なぜORDER BY
必要なのですか?前の開発者が単に類似のデータに row_number を付けたいだけの場合 (例: HI B、すべてのデータが BW、BW)、次のようにできます。
select
hi,ho,
row_number() over(partition by hi,ho)
from tbl;
しかし、悲しいかな、Oracle (および SQL Server も) は no のパーティションを許可しませんORDER BY
。一方、Postgresql ではORDER BY
、PARTITION はオプションです: http://www.sqlfiddle.com/#!1/27821/1
select
hi,ho,
row_number() over(partition by hi,ho)
from tbl;
あなたORDER BY
のパーティションは少し冗長に見えますが、以前の開発者のせいではありません。一部のデータベースではPARTITION
no が許可されていないためORDER BY
、並べ替えに適した候補の列を見つけることができない可能性があります。PARTITION 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 を使用できます ( newid()
SQL Server に使用します)。そのため、前の開発者が作成したものと同じ出力が得られますが、一部のデータベースでは許可PARTITION
されていないのは残念ですORDER BY
実際には、それは私を逃し、同じ組み合わせに番号を付ける正当な理由を見つけることができません (上記の例では BW、BW)。冗長なデータを持つデータベースの印象を与えています。どういうわけかこれを思い出しました:テーブルのレコードの同じリストから一意のレコードを 1 つ取得する方法は? テーブルに UNIQUE 制約がありません
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');
次に、あなたは PARTITION BY hi,ho; そして、あなたは ORDER BY hi,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 を使用するだけで、一意でない列の一意の列でソートできます。例はそれをより明確にします:
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
これは、PARTITION BY と ORDER BY の両方で同じ列を使用するクエリに似ています。
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