U radu sa bazama podataka često želimo da:

* numerišemo rezultate upita (1, 2, 3, 4…)
* pronađemo prvih N rezultata
* pronađemo najbolje rezultate po grupama
* uklonimo duplikate
* napravimo rang listu .....

Za to koristimo funkciju ROW_NUMBER().


Osnovna sintaksa

 
ROW_NUMBER() OVER (ORDER BY kolona) 

Ili sa grupisanjem:

ROW_NUMBER() OVER (PARTITION BY kolona ORDER BY kolona)

 📌 Objašnjenje:

Deo   Značenje
ROW_NUMBER() Funkcija koja dodeljuje redni broj
OVER Označava da je ovo prozor funkcija
ORDER BY Obavezno – definiše redosled numeracije
PARTITION BY (nije obavezno) – deli podatke u grupe

 


Primer 1 – Jednostavno numerisanje učenika

Kreiranje tabele

CREATE TABLE Ucenici (
    UcenikID INT PRIMARY KEY,
    Ime NVARCHAR(50),
    Prezime NVARCHAR(50),
    Prosek DECIMAL(3,2)
);

Unos podataka

INSERT INTO Ucenici VALUES
(1, 'Marko', 'Markovic', 4.50),
(2, 'Ana', 'Petrovic', 5.00),
(3, 'Jovan', 'Jovanovic', 3.80),
(4, 'Milica', 'Nikolic', 4.90),
(5, 'Ivan', 'Ilic', 4.20);

Upit:  Numerisanje po proseku (od najboljeg)

SELECT 
    ROW_NUMBER() OVER (ORDER BY Prosek DESC) AS RedniBroj,
    Ime,
    Prosek
FROM Ucenici;

Objašnjenje

ORDER BY Prosek DESC → Najveći prosek dobija broj 1
* Svaki sledeći učenik dobija sledeći broj

Rezultat:

| RedniBroj | Ime    | Prosek |
| --------- | ------ | ------ |
| 1         | Ana    | 5.00   |
| 2         | Milica | 4.90   |
| 3         | Marko  | 4.50   |
| 4         | Ivan   | 4.20   |
| 5         | Jovan  | 3.80   |

Primer 2 – Numerisanje unutar grupa (PARTITION BY) -> Sada želimo da numerišemo učenike po odeljenjima.

Kreiranje nove tabele

CREATE TABLE UceniciOdeljenje (
    UcenikID INT PRIMARY KEY,
    Ime NVARCHAR(50),
    Odeljenje NVARCHAR(10),
    Prosek DECIMAL(3,2)
);

Unos podataka

INSERT INTO UceniciOdeljenje VALUES
(1, 'Marko', 'III-1', 4.50),
(2, 'Ana', 'III-1', 5.00),
(3, 'Jovan', 'III-2', 3.80),
(4, 'Milica', 'III-2', 4.90),
(5, 'Ivan', 'III-1', 4.20),
(6, 'Sara', 'III-2', 5.00);

Upit

SELECT 
    ROW_NUMBER() OVER (PARTITION BY Odeljenje ORDER BY Prosek DESC) AS RedniBroj,
    Ime,
    Odeljenje,
    Prosek
FROM UceniciOdeljenje;

Objašnjenje

PARTITION BY Odeljenje → Svako odeljenje počinje numeraciju od 1
ORDER BY Prosek DESC → Najbolji učenik u odeljenju dobija broj 1

Rezultat:

| RedniBroj | Ime    | Odeljenje | Prosek |
| --------- | ------ | ------    | ------ |
| 1         | Ana    |   III-1   | 5.00   |
| 2         | Marko  |   III-1   | 4.50   |
| 3         | Ivan   |   III-1   | 4.20   |

| 1         | Sara   |   III-2   | 5.00   |
| 2         | Milica |   III-2   | 4.90   |
| 3         | Jovan  |   III-2   | 3.80   |


ROW_NUMBER() u podupitu

Često se koristi u podupitu da bismo izdvojili npr. samo prva 3 učenika.

Primer – Najbolja 3 učenika

SELECT *
FROM
(
    SELECT 
        ROW_NUMBER() OVER (ORDER BY Prosek DESC) AS RedniBroj,
        Ime,
        Prezime,
        Prosek
    FROM Ucenici
) AS Tabela
WHERE RedniBroj <= 3;

Objašnjenje

1. Prvo se numerišu svi učenici
2. Spoljašnji upit filtrira samo prve 3


Primer 3 – Uklanjanje duplikata

Kreiranje tabele

CREATE TABLE Proizvodi (
    ProizvodID INT,
    Naziv NVARCHAR(50),
    Cena DECIMAL(10,2)
);

Unos podataka

INSERT INTO Proizvodi VALUES
(1, 'Laptop', 60000),
(1, 'Laptop', 60000),
(2, 'Mis', 1500),
(2, 'Mis', 1500),
(3, 'Tastatura', 3000);

Uklanjanje duplikata

WITH CTE AS
(
    SELECT *,
           ROW_NUMBER() OVER (PARTITION BY ProizvodID ORDER BY ProizvodID) AS RN
    FROM Proizvodi
)
DELETE FROM CTE WHERE RN > 1;

Objašnjenje

* Svaki duplikat dobija broj
* Zadržava se prvi (RN = 1)
* Brišu se ostali


Vežbe sa rešenjima


Vežba 1 - Prikazati sve učenike numerisane po prezimenu (A-Ž).

Rešenje

SELECT 
    ROW_NUMBER() OVER (ORDER BY Prezime ASC) AS RedniBroj,
    Ime,
    Prezime
FROM Ucenici;

Vežba 2 - Pronaći najboljeg učenika u svakom odeljenju.

Rešenje

SELECT *
FROM
(
    SELECT 
        ROW_NUMBER() OVER (PARTITION BY Odeljenje ORDER BY Prosek DESC) AS RN,
        Ime,
        Odeljenje,
        Prosek
    FROM UceniciOdeljenje
) AS T
WHERE RN = 1;

Zadaci za vežbu kod kuće

🔹 Zadatak 1 - Prikazati 2 najskuplja proizvoda iz tabele Proizvodi.

🔹 Zadatak 2 - Numerisati učenike po odeljenjima, ali po rastućem proseku.

🔹 Zadatak 3 - Napraviti tabelu Radnici (RadnikID, Ime, Plata, Sektor).  Prikazati 3 radnika sa najvećom platom u svakom sektoru.


Treba zapamtiti

✅ ROW_NUMBER() uvek mora imati OVER()
✅ ORDER BY je obavezan
PARTITION BY deli podatke u grupe
✅ Često se koristi u podupitima
✅ Koristi se za top N rezultate i uklanjanje duplikata

Poslednja izmena: петак, 27. фебруар 2026, 10:27