Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Bernard Fedotoff

Développement .NET et mon quotidien

Comment utiliser PIVOT avec une liste d'éléments variables

Microsoft SQL 2005 introduit un nouvel opérateur relationnel PIVOT qui applique une rotation à un jeu d’enregistrements en croisant dynamiquement les valeurs d’une colonne unique en un jeu de colonnes multiples. C’est le même mécanisme que celui utilisé pour la création de tableaux croisés dynamique avec un tableur.

Imaginons le jeu d’enregistrements suivant contenu par une table temps, donnant par exemple par numéro de jour le nombre d’heure travaillé sur un projet :

Jour        Duree                  Nom

----------- ---------------------- --------------------

1           2,5                    Bernard

2           3                      Bernard

1           4                      Christine

3           6                      Christine

3           1,5                    Bernard

5           4                      Bernard
5           6                      Christine

 

En appliquant l’opérateur PIVOT suivant la requête suivante :

SELECT * FROM dbo.TestTemps

      PIVOT (sum(Duree) FOR Jour IN ([1], [2], [3], [4] )) as PVT

 

On obtient le jeu de données croisées suivant :

Nom             1      2      3      4      5

--------------- ------ ------ ------ ------ ------

Bernard         2,5    3      1,5    NULL   4

Christine       4      NULL   6      NULL   6

 

C’est donc un opérateur sur le principe très pratique pour croiser tout type de jeu d’enregistrements. Néanmoins, il possède un inconvénient majeur : la liste d’éléments explicités dans l’ensemble de l’opérateur IN est une liste finie qui ne peut pas être générée à partir d’une sous requête SELECT.

 

Se pose donc le problème de l’utilisation de PIVOT avec une liste d’éléments variables, comme par exemple le numéro de jour du mois donc le maximum vari de 28 à 31.

 

Voici une solution qui a été implémentée dans le cadre d’une gestion de suivi des temps passés par des ressources sur des projets (informatiques). Le principe de la solution est de générer dynamiquement une chaine de caractères qui représente l’ensemble à appliquer pour l’opérateur IN, et d’exécuter la requête avec une EXEC().

 

La modélisation (simplifiée) de la base de données est la suivante :

 

Tout d’abord, une table temporaire contenant l’ensemble des numéros de jour pour un mois donné et ayant des saisies de temps :

DECLARE @NumeroDeMois int ,@NumeroDeProject int

SET @NumeroDeMois = 1

 

DECLARE @ListeDesJours TABLE (IdJour int )

 

INSERT INTO @ListeDesJours (IdJour)

   SELECT DISTINCT  DAY(Date) FROM Temps

      WHERE MONTH(Date) = @NumeroDeMois

 

Puis une chaine de caractère est créée sur le format suivant ‘[1], [2], [3], …’ en balayant l’ensemble des enregistrements de la table temporaire :

DECLARE @Jours varchar(2000)

SET @Jours = ''

 

SELECT @Jours = @Jours + '[' + convert(varchar(2),IdJour) + '],'

FROM @ListeDesJours

 

Le dernier ‘,’ est retiré de la chaine de caractères :

 

SET @Jours = LEFT(@Jours, LEN(@Jours) - 1)

 

Enfin la requête PIVOT est exécutée par l’intermédiaire d’une EXEC(), en référençant la chaîne créée :

 

SET         @NumeroDeProjet = 1

EXEC( '

DECLARE @RecapitulatifDesTemps TABLE

(     Nom        varchar(50)

      ,IdJour           int

      ,Duree            float

)

INSERT INTO @RecapitulatifDesTemps

(

       Nom       

      ,IdJour    

      ,Duree

)

SELECT Nom, DAY(Date) as IdJour, Duree FROM Temps

      INNER JOIN  Employes    ON Temps.IdEmploye = Employes.IdEmploye

      WHERE temps.IdProjet = '+ @NumeroDeProjet +'

            AND MONTH(Temps.Date) = '+ @NumeroDeMois +'

      SELECT * FROM @RecapitulatifDesTemps

             PIVOT (sum(Duree) FOR IdJour IN (' + @Jours + ')) PVT'

)

 

Et le tour est joué. Il suffit de mettre tout cela en procédure stockée. Il est à noter que l’opérateur PIVOT n’est disponible que pour des bases de données fonctionnant avec SQL 2005 et en niveau de compatibilité SQL 2005 (90).

 Resultat

 

Vous trouverez en pièce jointe le code pour créer le contenu de la base de données de test et la procédure stockée.

 

 

 

Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :
Posted: samedi 9 décembre 2006 17:11 par bfedo
Classé sous :

Attachment(s): 061209_Pivot.zip

Commentaires

Pas de commentaires

Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- La suite ...Proposition de collaboration rédactionnelle entre les communautés de développeurs et Microsoft France par LucasR le il y a 9 heures et 9 minutes

- [Fun] Votre simulateur de vol avec Microsoft ESP par Julien Chable le il y a 14 heures et 52 minutes

- [Best Practices] Customisation du My Site : Comment le modifier en amont et en aval par The Mit's Blog le il y a 16 heures et 6 minutes

- Patrick Tisseghem s'en est allé ... par The Mit's Blog le il y a 16 heures et 50 minutes

- MS AutoCollage par alex# le il y a 17 heures et 35 minutes

- Un grand SharePointeur nous a quitte : Patrick Tisseghem manquera à la communauté ! par RedoBlog - The .NET Gentleman !!! le il y a 18 heures et 1 minutes

- [WPF] Comment charger dynamiquement un fichier XAML qui définit des eventhandler ? par Thomas Lebrun le 09-04-2008, 10:56

- Article sur le filtrage des modèles de site SharePoint par The Grib's Lair [Sébastien PICAMELOT - MVP SharePoint] le 09-04-2008, 00:11

- Adopter votre Redo en 3D - Clone Virtuel - avec photosynth par RedoBlog - The .NET Gentleman !!! le 09-04-2008, 00:07

- [Expression Web] Astuce de la Semaine : Mettre en bouton ses macros dans une barre d'outils. par Expression Web & Me le 09-03-2008, 20:48