sql >> Database >  >> RDS >> Oracle

Oracle 'Partition By' en 'Row_Number' trefwoord

PARTITION BY scheid sets, dit stelt u in staat om onafhankelijk te werken (ROW_NUMBER(),COUNT(),SUM(),etc) aan gerelateerde sets.

In uw zoekopdracht bestaat de gerelateerde set uit rijen met vergelijkbare cdt.country_code, cdt.account, cdt.currency. Wanneer u op die kolommen partitioneert en u ROW_NUMBER erop toepast. Die andere kolommen op die combinatie/set krijgen een volgnummer van ROW_NUMBER

Maar die vraag is grappig, als je partitie door een aantal unieke gegevens en je zet er een row_number op, zal het gewoon hetzelfde nummer produceren. Het is alsof je een ORDER BY doet op een partitie die gegarandeerd uniek is. Beschouw GUID bijvoorbeeld als een unieke combinatie van cdt.country_code, cdt.account, cdt.currency

newid() produceert GUID, dus wat verwacht je van deze uitdrukking?

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

...Juist, alle gepartitioneerde (geen was gepartitioneerd, elke rij is gepartitioneerd in hun eigen rij) rijen rijnummers zijn allemaal ingesteld op 1

In principe moet u partitioneren op niet-unieke kolommen. ORDER BY op OVER had de PARTITION BY nodig om een ​​niet-unieke combinatie te hebben, anders worden alle rijnummers 1

Dit zijn bijvoorbeeld uw gegevens:

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

Dan is dit analoog aan uw vraag:

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

Wat zal de output daarvan zijn?

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

Zie je de combinatie van HI HO? De eerste drie rijen hebben een unieke combinatie, daarom zijn ze ingesteld op 1, de B-rijen hebben dezelfde W, dus verschillende ROW_NUMBERS, ook met HI C-rijen.

Nu, waarom is de ORDER BY daar nodig? Als de vorige ontwikkelaar alleen een row_number op vergelijkbare gegevens wil zetten (bijv. HI B, alle gegevens zijn B-W, B-W), kan hij dit gewoon doen:

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

Maar helaas, Oracle (en ook Sql Server) staat geen partities toe zonder ORDER BY; terwijl in Postgresql, ORDER BY op PARTITION is optioneel:http://www.sqlfiddle.com/#!1/27821/1

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

Uw ORDER BY op je partitie ziet er een beetje overbodig uit, niet vanwege de fout van de vorige ontwikkelaar, sommige databases staan ​​​​PARTITION gewoon niet toe zonder ORDER BY , kan hij misschien geen goede kandidatenkolom vinden om op te sorteren. Als zowel PARTITION BY-kolommen als ORDER BY-kolommen hetzelfde zijn, verwijdert u gewoon de ORDER BY-kolom, maar aangezien sommige databases dit niet toestaan, kunt u dit gewoon doen:

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

Kunt u geen goede kolom vinden om vergelijkbare gegevens te sorteren? U kunt net zo goed op willekeurig sorteren, de gepartitioneerde gegevens hebben dezelfde waarden hoe dan ook. U kunt bijvoorbeeld GUID gebruiken (u gebruikt newid() voor SQL Server). Dus dat heeft dezelfde output gemaakt door de vorige ontwikkelaar, het is jammer dat een database PARTITION niet toestaat zonder ORDER BY

Maar echt, het ontgaat me en ik kan geen goede reden vinden om een ​​nummer op dezelfde combinaties te zetten (B-W, B-W in het bovenstaande voorbeeld). Het wekt de indruk dat de database redundante gegevens heeft. Op de een of andere manier herinnerde ik me hieraan:hoe krijg ik één uniek record uit dezelfde lijst met records uit een tabel? Geen unieke beperking in de tabel

Het ziet er echt mysterieus uit om te zien dat een PARTITION BY met dezelfde combinatie van kolommen met ORDER BY niet gemakkelijk de bedoeling van de code kan afleiden.

Live-test:http://www.sqlfiddle.com/#!3/27821/6

Maar zoals dbaseman ook heeft opgemerkt, is het nutteloos om op dezelfde kolommen te partitioneren en te ordenen.

Je hebt een set gegevens zoals deze:

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

Dan verdeel je door hi,ho; en dan BESTEL je DOOR hallo, ho. Het heeft geen zin om vergelijkbare gegevens te nummeren :-) 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;

Uitgang:

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

Zie je wel? Waarom moeten rijnummers op dezelfde combinatie worden gezet? Wat ga je analyseren op triple A,X, op double B,Y, op double C,Z? :-)

U hoeft alleen PARTITION te gebruiken op niet-unieke kolom, dan sorteert u op niet-unieke kolom(men)'s uniek -ing kolom. Voorbeeld maakt het duidelijker:

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 werkt op niet-unieke kolom, dan bestelt u op elke gepartitioneerde kolom op zijn unieke kolom (ho), ORDER BY ho

Uitgang:

HI  HO  NR
A   D   1
A   E   2
A   F   3
B   E   1
B   F   2
C   D   1
C   E   2

Die dataset is logischer

Live-test:http://www.sqlfiddle.com/#!3/d0b44/1

En dit is vergelijkbaar met uw zoekopdracht met dezelfde kolommen op zowel PARTITION BY als ORDER BY:

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

En dit is de output:

HI  HO  NR
A   D   1
A   E   1
A   F   1
B   E   1
B   F   1
C   D   1
C   E   1

Zie je wel? geen zin?

Live-test:http://www.sqlfiddle.com/#!3/d0b44/3

Eindelijk is dit misschien de juiste vraag:

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. Hoe kan ik in mijn geval SQL in Oracle schrijven?

  2. Top 5 PostgreSQL-hulpprogramma's voor het bewaken van query's

  3. SQL-updatetrigger alleen wanneer kolom is gewijzigd

  4. SQL niet gelijk aan (!=) Operator voor beginners