Imagine que tu bosses comme serveur (ou barista, si t'es branché café) dans un gros resto. Tous les jours, tu fais le total des tips que t'as gagnés. Mais y'a un truc : le resto est divisé en zones, et toi tu veux savoir combien de tips t'as eu dans chaque zone séparément. PARTITION BY, c'est ce que SQL utilise pour "découper le resto en zones".
Plus formellement, PARTITION BY est utilisé dans les fonctions window pour séparer toutes les lignes d'une table en groupes distincts (ou "partitions"). À l'intérieur de chaque groupe, la fonction window s'exécute à nouveau. C'est comme si tu appliquais la fonction séparément dans chaque "partition".
Exemple : comment ça marche
Disons qu'on a une table sales avec des données de ventes :
| region | salesperson | amount |
|---|---|---|
| North | Alice | 100 |
| North | Bob | 200 |
| South | Alice | 150 |
| South | Charlie | 250 |
Si on veut calculer combien chaque vendeur a gagné, mais séparément pour chaque région, PARTITION BY c'est exactement ce qu'il nous faut.
Syntaxe de PARTITION BY
La syntaxe est plutôt simple :
fonction_window() OVER (PARTITION BY colonne_ou_colonnes)
fonction_window()— genreSUM(),AVG(),ROW_NUMBER()et compagnie.PARTITION BY colonne— indique sur quelle colonne tu veux découper les lignes.OVER()— c'est l'opérateur qui dit à SQL : "Fais ça dans la fenêtre spécifiée".
Exemple : somme par groupe
Calculons la somme des ventes pour chaque région :
SELECT
region,
salesperson,
amount,
SUM(amount) OVER (PARTITION BY region) AS total_sales_by_region
FROM sales;
Le résultat sera :
| region | salesperson | amount | total_sales_by_region |
|---|---|---|---|
| North | Alice | 100 | 300 |
| North | Bob | 200 | 300 |
| South | Alice | 150 | 400 |
| South | Charlie | 250 | 400 |
Qu'est-ce qui se passe ? SQL découpe les lignes en groupes selon la colonne region (North et South), puis applique la fonction SUM() séparément pour chaque groupe. Du coup, les lignes du groupe "North" ont toutes la même somme, et celles du groupe "South" aussi.
Exemples d'utilisation de PARTITION BY
Voyons comment PARTITION BY peut servir dans des cas concrets.
Exemple 1 : Ranking à l'intérieur d'un groupe
Imaginons qu'on veut classer les vendeurs dans chaque région selon le montant des ventes. Pour ça, on peut utiliser une combinaison de PARTITION BY et la fonction RANK() :
SELECT
region,
salesperson,
amount,
RANK() OVER (PARTITION BY region ORDER BY amount DESC) AS rank_in_region
FROM sales;
Résultat :
| region | salesperson | amount | rank_in_region |
|---|---|---|---|
| North | Bob | 200 | 1 |
| North | Alice | 100 | 2 |
| South | Charlie | 250 | 1 |
| South | Alice | 150 | 2 |
La fonction RANK() attribue un rang dans chaque groupe region, en commençant à 1. À chaque fois, les rangs recommencent à 1 pour chaque groupe.
Exemple 2 : Comparer chaque valeur à la moyenne du groupe
Disons qu'on veut voir combien chaque vendeur a fait par rapport à la moyenne de sa région. On utilise AVG() :
SELECT
region,
salesperson,
amount,
AVG(amount) OVER (PARTITION BY region) AS avg_sales_by_region,
amount - AVG(amount) OVER (PARTITION BY region) AS diff_from_avg
FROM sales;
Résultat :
| region | salesperson | amount | avg_sales_by_region | diff_from_avg |
|---|---|---|---|---|
| North | Alice | 100 | 150 | -50 |
| North | Bob | 200 | 150 | 50 |
| South | Alice | 150 | 200 | -50 |
| South | Charlie | 250 | 200 | 50 |
D'abord, SQL découpe les lignes en groupes selon region. Ensuite, il calcule la moyenne AVG(amount) pour chaque groupe. Enfin, pour chaque ligne, il calcule la différence entre sa valeur et la moyenne.
Exemple 3 : Numéroter les lignes dans chaque groupe
Par exemple, tu veux numéroter toutes les transactions dans chaque groupe de région. On utilise ROW_NUMBER() :
SELECT
region,
salesperson,
amount,
ROW_NUMBER() OVER (PARTITION BY region ORDER BY amount DESC) AS row_number
FROM sales;
Résultat :
| region | salesperson | amount | row_number |
|---|---|---|---|
| North | Bob | 200 | 1 |
| North | Alice | 100 | 2 |
| South | Charlie | 250 | 1 |
| South | Alice | 150 | 2 |
Comparaison avec GROUP BY
On confond souvent PARTITION BY et GROUP BY. Comparons-les :
GROUP BY
GROUP BY change la structure du résultat — il transforme les lignes de la table en agrégats. Par exemple :
SELECT
region,
SUM(amount) AS total_sales
FROM sales
GROUP BY region;
Résultat :
| region | total_sales |
|---|---|
| North | 300 |
| South | 400 |
Ici, on perd l'info sur les vendeurs, parce que les données sont agrégées.
PARTITION BY
PARTITION BY, au contraire, ne change pas la structure. On voit toujours chaque ligne, mais on a des valeurs en plus, calculées par groupe. Donc, PARTITION BY permet d'agréger sans perdre les détails.
Erreurs fréquentes avec PARTITION BY
Erreur 1 : Oubli de PARTITION BY
Parfois tu veux grouper des données, mais t'oublies de mettre PARTITION BY. Par exemple :
SELECT
region,
salesperson,
amount,
SUM(amount) OVER () AS total_sales
FROM sales;
Résultat :
| region | salesperson | amount | total_sales |
|---|---|---|---|
| North | Alice | 100 | 700 |
| North | Bob | 200 | 700 |
| South | Alice | 150 | 700 |
| South | Charlie | 250 | 700 |
Ici, SUM(amount) est calculé pour toute la table, pas séparément pour chaque région. Si tu veux tenir compte des régions, n'oublie pas de mettre PARTITION BY region.
Erreur 2 : Mauvais ordre dans ORDER BY
L'ordre des lignes dans la fenêtre est important pour des fonctions comme RANK() ou ROW_NUMBER(). Fais gaffe quand tu utilises ORDER BY dans OVER().
GO TO FULL VERSION