Les rapports analytiques avec filtrage dynamique, regroupement et agrégation selon de nombreux paramètres constituent le cœur des applications BI et Data WareHouse. Auparavant, de telles tâches étaient résolues uniquement par des requêtes statiques, mais avec l'augmentation des exigences, la nécessité de construire dynamiquement des SQL à la volée est apparue : le nombre de champs et de regroupements est déterminé par l'utilisateur ou l'application.
Problème — impossibilité de déterminer à l'avance toutes les variantes de champs pour le regroupement et l'agrégation. Il faut construire les requêtes dynamiquement, ce qui est susceptible d'entraîner des erreurs et une dégradation des performances en cas de planification de requêtes de mauvaise qualité et d'utilisation d'index inappropriés.
Solution — mettre en œuvre la construction de requêtes à l'aide de SQL dynamique (par exemple, via EXEC ou sp_executesql en T-SQL), en formant la liste des champs pour SELECT, GROUP BY et les fonctions d'agrégation correspondantes à partir des paramètres de l'utilisateur. Dans ce cas, un soin particulier doit être apporté à l'échappement des noms de champs et à la protection contre les injections SQL. Exemple pour SQL Server :
DECLARE @select_fields nvarchar(max) = N'customer_id, year'; DECLARE @agg_fields nvarchar(max) = N'SUM(amount) AS total, COUNT(*) AS row_count'; DECLARE @group_by nvarchar(max) = N'customer_id, year'; DECLARE @sql nvarchar(max) = N'SELECT ' + @select_fields + ', ' + @agg_fields + N' FROM sales WHERE sale_date >= @start AND sale_date <= @end GROUP BY ' + @group_by; EXEC sp_executesql @sql, N'@start DATE, @end DATE', @start='2023-01-01', @end='2023-12-31';
Caractéristiques clés :
Peut-on créer à l'avance une requête universelle avec CASE pour tous les regroupements possibles au lieu de SQL dynamique ?
Non, CASE permettra de faire des calculs dans SELECT, mais ne pourra pas former GROUP BY sur des champs déterminés dynamiquement — ils doivent tout de même être spécifiés explicitement. L'approche statique est trop limitée pour une BI analytique vivante.
Faut-il utiliser des paramètres de requête SQL lors de la construction dynamique de WHERE, ou peut-on insérer des valeurs directement dans le texte ?
Utilisez toujours des paramètres (par exemple, via sp_executesql), sinon vous risquez des vulnérabilités d'injection SQL et les valeurs protégées (par exemple, les apostrophes dans les chaînes) seront mal traitées.
Un index sur toutes les combinaisons possibles de champs accélérera-t-il n'importe quel rapport ?
Non, la création d'un index composite sur des dizaines de champs entraîne une augmentation de la taille de l'index et une diminution de la vitesse d'insertion/mise à jour, tout en accélérant seulement un nombre très limité de scénarios. N'indexez que les champs/groupes réellement nécessaires.
Dans un ancien rapport BI, 30 variantes de regroupement ont été "rigidement" codées avec des if-else dans l'application. Chaque nouveau paramètre nécessitait une mise à jour du code source et du schéma des index. Avantages :
Inconvénients :
Utilisation de SQL dynamique avec formation de select/group by à la volée, code SQL dans un module séparé, paramètres strictement échappés. L'ajout de nouveaux champs — simplement un réglage du référentiel, les index sont ajoutés en fonction de la fréquence de filtrage. Avantages :
Inconvénients :