Le calcul des totaux cumulés et des sommes courantes a traditionnellement été résolu dans SQL par le biais de fonctions de fenêtre (par exemple, SUM() OVER(ORDER BY ...)), cependant, dans les versions plus anciennes ou simplifiées des SGBD, seules les sous-requêtes et les regroupements sont disponibles. Historiquement, les architectes de bases de données cherchaient des solutions alternatives jusqu'à l'apparition de la norme SQL:2003 avec le soutien des fonctions de fenêtre.
Problème — en l'absence de fonctions de fenêtre, il est nécessaire de calculer explicitement la somme de toutes les valeurs précédentes pour chaque ligne, ce qui entraîne des requêtes imbriquées O(N^2) pour des ensembles de données suffisamment grands, à moins d'appliquer des astuces.
Solution:
On utilise généralement des sous-requêtes corrélées ou des tables temporaires avec mise à jour des valeurs :
Exemple de code :
-- Somme cumulée par requête corrélée SELECT t1.id, t1.amount, ( SELECT SUM(t2.amount) FROM transactions t2 WHERE t2.id <= t1.id ) AS running_total FROM transactions t1 ORDER BY t1.id; -- Via une table temporaire avec mise à jour manuelle des valeurs CREATE TEMPORARY TABLE temp_running (id INT, amount INT, running_total INT); -- On parcourt les lignes avec du code externe (par exemple, pl/pgsql), en ajoutant la somme séquentiellement
Caractéristiques clés :
Fournit-elle un tri garanti par ORDER BY dans une sous-requête corrélée ?
Non — la sous-requête n'influence pas nécessairement le résultat lui-même. Le tri de l'ensemble final est toujours défini de l'extérieur dans la requête principale : le total dépend uniquement de la filtration par WHERE.
Peut-on paralléliser le calcul de la somme cumulée avec cette approche ?
Non — l'ordre est très important, surtout lors de calculs dépendant des lignes précédentes, ce qui rend une simple parallélisation impossible dans un SQL ordinaire.
Pourquoi la sous-requête corrélée est-elle si lente avec un grand nombre de lignes ?
Parce que pour chaque ligne, la somme est recalculée sur l'ensemble des lignes précédentes. Cela entraîne O(N^2) opérations. Sur un échantillon de 100 000 lignes, cela peut déjà prendre des minutes, voire des heures.
Un analyste a calculé le revenu cumulé quotidien par date via une sous-requête corrélée, alors que des id supprimés apparaissaient parfois dans la table (trous). La somme finale présentait des chutes brusques et dépendait non pas de la date, mais de l'ordre des id.
Avantages:
Inconvénients:
Un ingénieur a déplacé le traitement de la somme cumulée dans un script ETL (Python/pandas), puis a téléchargé les valeurs finales dans une table distincte, synchronisant uniquement les nouvelles entrées. Les totaux étaient toujours concordants par date, le code fonctionnait rapidement et avec des millions d'enregistrements.
Avantages:
Inconvénients: