Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Słowo kluczowe Oracle „Partition By” i „Row_Number”

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


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Rozpoczęcie blogowania dla HTML5 i CSS3

  2. Jak uruchomić tworzenie tabeli DDL z EXECUTE IMMEDIATE w bazie danych Oracle?

  3. Słowo kluczowe Oracle „Partition By” i „Row_Number”

  4. PL/SQL:Błąd PLS-00306:nieprawidłowa liczba lub typy argumentów w wywołaniu wywołanym dla tabeli liczb

  5. Opcje formatowania SQLcl (Oracle)