Salt la conținutul principal
Modulul 7 · Lecția 2 din 426/57 în curs~14 min
Lecții din modul (2/4)

Funcții ferestre: clasamente și calcule pe grup

O funcție fereastră este o funcție care operează pe un „grup de rânduri” (fereastra) dar — spre deosebire de GROUP BY — nu reduce numărul de rânduri: o valoare calculată peste fereastră este atașată fiecărui rând al rezultatul final.

Este instrumentul potrivit pentru clasamente, numerotare progresivă, procente peste un total de grup și multe alte operațiuni care sunt incomode sau imposibil cu GROUP BY.

Sintaxa: function() OVER (…)

SQL
ROW_NUMBER() OVER (PARTITION BY colonna ORDER BY colonna2)

Componente:

  • PARTITION BY — definește „grupurile” (cum ar fi GROUP BY, dar rândurile stați separat);
  • ORDER BY în interiorul OVER(…) — definește ordinea în cadrul compartimentare.

OVER () (paranteze goale) înseamnă „întregul tabel ca o singură fereastră”. Util pentru calcule precum „procent din total”.

Funcții de clasare

SQL
ROW_NUMBER() OVER (PARTITION BY p ORDER BY o)
RANK()       OVER (PARTITION BY p ORDER BY o)
DENSE_RANK() OVER (PARTITION BY p ORDER BY o)

Diferențe (cu valori 100, 100, 90, 80):

FuncțiaPoziții
ROW_NUMBER1, 2, 3, 4 (întotdeauna unic)
RANK1, 1, 3, 4 (legăturile împărtășesc o poziție, lasă „goluri”)
DENSE_RANK1, 1, 2, 3 (legăturile împart o poziție, fără lacune)

Exemplu: clasarea produselor pe categorie

SQL
SELECT name,
       category_id,
       price,
       RANK() OVER (PARTITION BY category_id ORDER BY price DESC) AS rank
FROM   products
ORDER BY category_id, rank;

Pentru fiecare category_id, RANK repornește de la 1 și comandă descendent preț: obțineți clasamentul produselor în cadrul fiecărei categorii, într-una singură impuscat.

Numerotare progresivă

SQL
-- Progressive order number for each customer:
SELECT id,
       customer_id,
       ordered_at,
       ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY ordered_at) AS row_num
FROM   orders
ORDER BY customer_id, row_num;

Prima comandă a fiecărui client va avea row_num = 1, a doua 2 etc.

Încearcă

Exercițiu#sql.m7.l2.e1
Încercări: 0Se încarcă…

Pentru fiecare produs afișați numele, categoria_id, prețul și clasamentul (clasamentul prin preț descendent ÎN cadrul categoriei; utilizați RANK). Ordonați după categorie_id crescător și rang crescător.

Se încarcă editorul...
Afișează indiciu

PARTITION BY categorie_id grupuri, ORDER BY pret DESC comenzi din cadrul grupului.

Soluție disponibilă după 3 încercări

Exercițiu de revizuire

Exercițiu#sql.m7.l2.e2
Încercări: 0Se încarcă…

Pentru fiecare comandă afișați id, customer_id, ordered_at și row_num (ROW_NUMBER progresiv per client, ordonat crescător ordered_at). Comandă după customer_id și row_num.

Se încarcă editorul...
Afișează indiciu

ROW_NUMBER este întotdeauna unic în cadrul partiției.

Soluție disponibilă după 3 încercări