PARTITION BY
segreguj zestawy, dzięki temu możesz pracować (ROW_NUMBER(),COUNT(),SUM(),itd.) na powiązanym zestawie niezależnie.
W zapytaniu powiązany zestaw składa się z wierszy z podobnym kodem cdt.country_code, cdt.account, cdt.currency. Kiedy podzielisz te kolumny na partycje i zastosujesz do nich ROW_NUMBER. Te inne kolumny w tej kombinacji/zestawie otrzymają kolejny numer z ROW_NUMBER
Ale to zapytanie jest zabawne, jeśli twoja partycja według jakichś unikalnych danych i umieścisz na niej numer_wiersza, to po prostu wygeneruje ten sam numer. To tak, jakbyś wykonał ORDER BY na partycji, która gwarantuje unikalność. Przykład, pomyśl o identyfikatorze GUID jako unikalnej kombinacji cdt.country_code, cdt.account, cdt.currency
newid()
tworzy GUID, więc czego możesz oczekiwać po tym wyrażeniu?
select
hi,ho,
row_number() over(partition by newid() order by hi,ho)
from tbl;
...Tak, wszystkie partycjonowane (żaden nie był partycjonowany, każdy wiersz jest podzielony na partycje we własnym wierszu) wiersze row_numbers są ustawione na 1
Zasadniczo powinieneś partycjonować na nieunikatowych kolumnach. ORDER BY w dniu OVER wymagało, aby PARTITION BY miała nieunikalną kombinację, w przeciwnym razie wszystkie numery wierszy staną się 1
Przykład, to są Twoje dane:
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');
To jest analogiczne do Twojego zapytania:
select
hi,ho,
row_number() over(partition by hi,ho order by hi,ho)
from tbl;
Jaki będzie tego wynik?
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
Widzisz połączenie HI HO? Pierwsze trzy wiersze mają unikalną kombinację, dlatego są ustawione na 1, wiersze B mają takie same W, stąd różne ROW_NUMBERS, podobnie jak wiersze HI C.
Dlaczego teraz ORDER BY
potrzebne tam? Jeśli poprzedni programista chciał po prostu umieścić numer wiersza na podobnych danych (np. HI B, wszystkie dane są czarno-białe, czarno-białe), może po prostu zrobić to:
select
hi,ho,
row_number() over(partition by hi,ho)
from tbl;
Ale niestety, Oracle (i Sql Server również) nie zezwala na partycje bez ORDER BY
; podczas gdy w Postgresql ORDER BY
na PARTYCJI jest opcjonalne:http://www.sqlfiddle.com/#!1/27821/1
select
hi,ho,
row_number() over(partition by hi,ho)
from tbl;
Twoje ORDER BY
na twojej partycji wygląda na nieco zbędną, nie z powodu winy poprzedniego programisty, niektóre bazy danych po prostu nie pozwalają na PARTITION
bez ORDER BY
, może nie być w stanie znaleźć dobrej kolumny kandydata do sortowania. Jeśli obie kolumny PARTITION BY i ORDER BY są takie same, po prostu usuń ORDER BY, ale ponieważ niektóre bazy danych na to nie pozwalają, możesz po prostu zrobić to:
SELECT cdt.*,
ROW_NUMBER ()
OVER (PARTITION BY cdt.country_code, cdt.account, cdt.currency
ORDER BY newid())
seq_no
FROM CUSTOMER_DETAILS cdt
Nie możesz znaleźć dobrej kolumny do sortowania podobnych danych? Równie dobrze możesz sortować losowo, dane podzielone na partycje mają te same wartości W każdym razie. Możesz na przykład użyć identyfikatora GUID (używasz newid()
dla SQL Server). Tak więc ma to samo wyjście wykonane przez poprzedniego programistę, szkoda, że niektóre bazy danych nie zezwalają na PARTITION
bez ORDER BY
Chociaż tak naprawdę umyka mi to i nie mogę znaleźć dobrego powodu, aby umieścić numer w tych samych kombinacjach (B-W, B-W w powyższym przykładzie). Sprawia wrażenie, że baza danych zawiera nadmiarowe dane. Jakoś przypomniało mi się to:Jak uzyskać jeden unikalny rekord z tej samej listy rekordów z tabeli? Brak unikalnego ograniczenia w tabeli
To naprawdę wygląda tajemniczo, widząc PARTITION BY z taką samą kombinacją kolumn z ORDER BY, nie można łatwo wywnioskować intencji kodu.
Test na żywo:http://www.sqlfiddle.com/#!3/27821/6
Ale jak zauważył dbaseman, partycjonowanie i porządkowanie w tych samych kolumnach jest bezużyteczne.
Masz taki zestaw danych:
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');
Następnie PARTITION BY cześć,ho; a potem ZAMÓWIĆ BY cześć,ho. Nie ma sensu numerować podobnych danych :-) 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;
Wyjście:
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
Widzieć? Po co umieszczać numery rzędów w tej samej kombinacji? Co przeanalizujesz na potrójnym A,X, na podwójnym B,Y, na podwójnym C,Z? :-)
Wystarczy użyć PARTITION w nieunikalnej kolumnie, a następnie posortować według unikalnych kolumn nieunikalnych -ing kolumna. Przykład będzie bardziej zrozumiały:
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
działa na nieunikalnej kolumnie, a następnie w każdej partycjonowanej kolumnie zamawiasz jej unikatową kolumnę (ho), ORDER BY ho
Wyjście:
HI HO NR
A D 1
A E 2
A F 3
B E 1
B F 2
C D 1
C E 2
Ten zestaw danych ma więcej sensu
Test na żywo:http://www.sqlfiddle.com/#!3/d0b44/1
I to jest podobne do twojego zapytania z tymi samymi kolumnami zarówno w PARTITION BY, jak i ORDER BY:
select
hi,ho,
row_number() over(partition by hi,ho order by hi,ho) as nr
from tbl;
A oto wynik:
HI HO NR
A D 1
A E 1
A F 1
B E 1
B F 1
C D 1
C E 1
Widzieć? nie ma sensu?
Test na żywo:http://www.sqlfiddle.com/#!3/d0b44/3
Wreszcie może to być właściwe zapytanie:
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