- En bref sur les tableaux croisés dynamiques
- Pivotement des données au moyen d'outils (dbForge Studio for MySQL)
- Pivoter des données au moyen de SQL
- Exemple basé sur T-SQL pour SQL Server
- Exemple pour MySQL
- Automatisation du pivotement des données, création dynamique de requêtes
En bref sur les tableaux croisés dynamiques
Cet article traite de la transformation des données d'un tableau de lignes en colonnes. Une telle transformation est appelée tableaux croisés dynamiques. Souvent, le résultat du pivot est un tableau récapitulatif dans lequel les données statistiques sont présentées sous la forme appropriée ou requise pour un rapport.
En outre, une telle transformation de données peut être utile si une base de données n'est pas normalisée et que les informations y sont stockées sous une forme non optimale. Ainsi, lors de la réorganisation de la base de données et du transfert de données vers de nouvelles tables ou de la génération d'une représentation de données requise, le pivot de données peut être utile, c'est-à-dire en déplaçant les valeurs des lignes vers les colonnes résultantes.
Vous trouverez ci-dessous un exemple de l'ancienne table de produits - ProductsOld et de la nouvelle - ProductsNew. C'est par la transformation des lignes en colonnes qu'un tel résultat peut être facilement atteint.
Voici un exemple de tableau croisé dynamique.
Pivoter les données au moyen d'outils (dbForge Studio for MySQL)
Il existe des applications qui disposent d'outils permettant d'implémenter le pivot de données dans un environnement graphique pratique. Par exemple, dbForge Studio pour MySQL inclut la fonctionnalité de tableaux croisés dynamiques qui fournit le résultat souhaité en quelques étapes seulement.
Regardons l'exemple avec un tableau simplifié des commandes - PurchaseOrderHeader .
CREATE TABLE PurchaseOrderHeader ( PurchaseOrderID INT(11) NOT NULL, EmployeeID INT(11) NOT NULL, VendorID INT(11) NOT NULL, PRIMARY KEY (PurchaseOrderID));INSERT PurchaseOrderHeader(PurchaseOrderID, EmployeeID, VendorID) VALUES (1 , 258, 1580);INSERT PurchaseOrderHeader(PurchaseOrderID, EmployeeID, VendorID) VALUES (2, 254, 1496);INSERT PurchaseOrderHeader(PurchaseOrderID, EmployeeID, VendorID) VALUES (3, 257, 1494);INSERT PurchaseOrderHeader(PurchaseOrderID, EmployeeID, VendorID ) VALEURS (4, 261, 1650) ; , EmployeeID, VendorID) VALEURS (7, 255, 1678); INSERT PurchaseOrderHeader(PurchaseOrderID, EmployeeID, VendorID) VALUES (10, 250, 1602);INSERT PurchaseOrderHeader(PurchaseOrderID, EmployeeID, VendorID) VALUES (11, 258, 1540);...
Supposons que nous devions faire une sélection dans le tableau et déterminer le nombre de commandes passées par certains employés auprès de fournisseurs spécifiques. La liste des employés pour lesquels des informations sont nécessaires - 250, 251, 252, 253, 254.
Une vue préférée pour le rapport est la suivante.
La colonne de gauche VendorID affiche les identifiants des fournisseurs ; colonnes Emp250 , Emp251 , Emp252 , Emp253 , et Emp254 afficher le nombre de commandes.
Pour y parvenir dans dbForge Studio pour MySQL, vous devez :
- Ajoutez le tableau en tant que source de données pour la représentation "Tableau croisé dynamique" du document. Dans l'explorateur de base de données, cliquez avec le bouton droit sur PurchaseOrderHeader tableau et sélectionnez Envoyer à puis Tableau croisé dynamique dans le menu contextuel.
- Spécifiez une colonne dont les valeurs seront des lignes. Faites glisser le VendorID colonne dans la case "Déposer les champs de lignes ici".
- Spécifiez une colonne dont les valeurs seront des colonnes. Faites glisser le EmployeeID colonne dans la case "Déposer les champs de colonne ici". Vous pouvez également définir un filtre pour les employés requis (250, 251, 252, 253, 254).
- Spécifiez une colonne dont les valeurs seront les données. Faites glisser le PurchaseOrderID colonne dans la case "Déposer les éléments de données ici".
- Dans les propriétés de PurchaseOrderID colonne, spécifiez le type d'agrégation – Nombre de valeurs .
Nous avons rapidement obtenu le résultat dont nous avions besoin.
Pivoter des données au moyen de SQL
Bien entendu, la transformation des données peut être effectuée au moyen d'une base de données en écrivant une requête SQL. Mais il y a un léger hic, MySQL n'a pas de déclaration spécifique permettant de faire cela.
Exemple basé sur T-SQL pour SQL Server
Par exemple, SqlServer et Oracle ont l'opérateur PIVOT qui permet d'effectuer une telle transformation de données. Si nous travaillions avec SqlServer, notre requête ressemblerait à ceci.
SELECT VendorID ,[250] AS Emp1 ,[251] AS Emp2 ,[252] AS Emp3 ,[253] AS Emp4 ,[254] AS Emp5FROM (SELECT PurchaseOrderID ,EmployeeID ,VendorID FROM Purchasing.PurchaseOrderHeader) pPIVOT( COUNT (PurchaseOrderID) FOR EmployeeID IN ([250], [251], [252], [253], [254])) AS tORDER BY t.VendorID ;
Exemple pour MySQL
Dans MySQL, nous devrons utiliser les moyens de SQL. Les données doivent être regroupées par la colonne du fournisseur - VendorID , et pour chaque employé requis (EmployeeID ), vous devez créer une colonne séparée avec une fonction d'agrégation.
Dans notre cas, nous devons calculer le nombre de commandes, nous utiliserons donc la fonction d'agrégation COUNT.
Dans la table source, les informations sur tous les employés sont stockées dans une colonne EmployeeID , et nous devons calculer le nombre de commandes pour un employé particulier, nous devons donc apprendre à notre fonction d'agrégation à ne traiter que certaines lignes.
La fonction d'agrégation ne prend pas en compte les valeurs NULL, et nous utilisons cette particularité pour nos besoins.
Vous pouvez utiliser l'opérateur conditionnel IF ou CASE qui renverra une valeur spécifique pour l'employé souhaité, sinon renverra simplement NULL ; par conséquent, la fonction COUNT ne comptera que les valeurs non NULL.
La requête résultante est la suivante :
SELECT VendorID, COUNT(IF(EmployeeID =250, PurchaseOrderID, NULL)) AS Emp250, COUNT(IF(EmployeeID =251, PurchaseOrderID, NULL)) AS Emp251, COUNT(IF(EmployeeID =252, PurchaseOrderID, NULL) ) AS Emp252, COUNT(IF(EmployeeID =253, PurchaseOrderID, NULL)) AS Emp253, COUNT(IF(EmployeeID =254, PurchaseOrderID, NULL)) AS Emp254FROM PurchaseOrderHeader pWHERE p.EmployeeID BETWEEN 250 AND 254GROUP BY VendorID;
Ou même comme ça :
VendorID, COUNT(IF(EmployeeID =250, 1, NULL)) AS Emp250, COUNT(IF(EmployeeID =251, 1, NULL)) AS Emp251, COUNT(IF(EmployeeID =252, 1, NULL)) AS Emp252, COUNT(IF(EmployeeID =253, 1, NULL)) AS Emp253, COUNT(IF(EmployeeID =254, 1, NULL)) AS Emp254FROM PurchaseOrderHeader pWHERE p.EmployeeID BETWEEN 250 AND 254GROUP BY VendorID ;
Lorsqu'il est exécuté, un résultat familier est obtenu.
Automatiser le pivot des données, créer des requêtes dynamiquement
Comme on peut le voir, la requête a une certaine cohérence, c'est-à-dire que toutes les colonnes transformées sont formées de la même manière, et pour écrire la requête, vous devez connaître les valeurs spécifiques de la table. Pour former une requête pivot, vous devez passer en revue toutes les valeurs possibles et ensuite seulement vous devez écrire la requête. Alternativement, vous pouvez transmettre cette tâche à un serveur pour qu'il obtienne ces valeurs et exécute dynamiquement la tâche de routine.
Revenons au premier exemple, dans lequel nous avons formé la nouvelle table ProductsNew à partir de ProductsOld table. Là, les valeurs des propriétés sont limitées, et on ne peut même pas connaître toutes les valeurs possibles; nous n'avons que des informations sur l'endroit où les noms des propriétés et leur valeur sont stockés. Ce sont la propriété et Valeur colonnes, respectivement.
Tout l'algorithme de création de la requête SQL se résume à l'obtention des valeurs, à partir desquelles de nouvelles colonnes et concaténations de parties immuables de la requête seront formées.
SELECT GROUP_CONCAT( CONCAT( ' MAX(IF(Property =''', t.Property, ''', Value, NULL)) AS ', t.Property ) ) INTO @PivotQueryFROM (SELECT Property FROM ProductOld GROUP BY Propriété) t ; SET @PivotQuery =CONCAT('SELECT ProductID,', @PivotQuery, ' FROM ProductOld GROUP BY ProductID');
La variable @PivotQuery stockera notre requête, le texte a été formaté pour plus de clarté.
SELECT ProductID, MAX(IF(Property ='Color', Value, NULL)) AS Color, MAX(IF(Property ='Name', Value, NULL)) AS Name, MAX(IF(Property ='ProductNumber ', Valeur, NULL)) AS ProductNumber, MAX(IF(Property ='Size', Value, NULL)) AS Size, MAX(IF(Property ='SizeUnitMeasureCode', Value, NULL)) AS SizeUnitMeasureCodeFROM ProductOldGROUP BY ProductIDAprès l'avoir exécuté, nous obtiendrons le résultat souhaité correspondant au schéma de la table ProductsNew.
De plus, la requête de la variable @PivotQuery peut être exécutée dans le script à l'aide de l'instruction MySQL EXECUTE.Instruction PREPARE FROM @PivotQuery;instruction EXECUTE;DEALLOCATE instruction PREPARE;