1
votes

Utilisation du pivot dans une instruction SELECT

J'ai une table avec des colonnes:

SELECT Date,Name,Result
FROM tbl_Results
WHERE (..conditions..)
)
PIVOT (
Result FOR Date in
([1],[2],[3],[2],[5])
)

Je travaille sur l'instruction SELECT qui me donne un résultat comme celui-ci:

[Name]  [2010-01-01] [2010-07-04]
Name01       11           32
Name02       22           54

J'ai essayé la fonction PIVOT, mais cela ne fonctionne pas.

SELECT * FROM (

[Date]       [Name]     [Result]
2010-01-01   Name01     11
2010-01-01   Name02     22
2010-07-04   Name01     32
2010-07-04   Name02     54

Message d'erreur

Syntaxe incorrecte à côté du mot-clé "PIVOT".

C'est SQL Server 2005, je ne sais pas si PIVOT est disponible?

Peut-être utiliser une autre fonction?

Aussi je ne sais pas comment faire définir le nom de la colonne comme date de sélection.

MISE À JOUR

Merci pour toutes les réponses. Le problème est que je ne sais pas combien de colonnes il y aura dans le résultat. Je ne peux donc pas utiliser des valeurs de dates fixes telles que «2010-07-04». La date est utilisée "à la volée" dans le relevé du tableau.


2 commentaires

PIVOT était disponible dans SQL Server 2005, cependant, 2005 si longtemps sans support. Je conseillerais vraiment de regarder les chemins de mise à niveau. Quant à votre requête, vous en avez supprimé une partie, et je soupçonne que l'erreur se trouve dans le SQL expurgé.


Larnu, merci pour votre réponse rapide. Je réalise que la mise à niveau est nécessaire. Mais aussi l'application est écrite en asp.net 2.0 et se trouve actuellement sur un hébergement mutualisé (serveur IIS). Il devrait donc être déplacé, application et base de données vers un nouveau serveur. Comme je l'ai mentionné dans les articles, il n'est pas possible de faire une conversion de asp.net 2.0 vers asp.net core de manière automatisée. Devrait probablement écrire en tant que nouveau projet à partir de zéro.


3 Réponses :


2
votes

Utilisez simplement l'agrégation conditionnelle:

select name,
       max(case when date = '2010-01-01' then result end) as result_20100101,
       max(case when date = '2010-07-04' then result end) as result_20100704
from tbl_results
where . . . 
group by name;

Ensuite, mettez à niveau votre système vers une base de données prise en charge.


1 commentaires

Merci d'avoir répondu. Le problème est que je ne peux pas utiliser de valeurs de dates fixes dans la déclaration, il peut s'agir d'un nombre de colonnes différent.



0
votes

Essayez ceci -

SELECT *  FROM
(
    SELECT A.Name,A.Date,A.Result 
    FROM your_table A
    --WHERE A.Name = 'Name01'
) A
PIVOT
(
    SUM(Result)
    FOR Date IN ([2010-01-01],[2010-07-04])
)PVT


1 commentaires

Merci d'avoir répondu. Je l'essaie, mais je n'obtiens que des valeurs nulles dans les colonnes de dates (pas de résultat). De plus, je ne peux pas utiliser de valeurs de dates fixes, il peut s'agir d'un nombre de colonnes différent.



1
votes

Je vois dans votre mise à jour que vous aurez besoin de DYNAMIC SQL. Voici une procédure stockée qui fera pivoter pratiquement n'importe quelle table ou requête ad hoc. Il existe également un utilitaire supplémentaire permettant de créer des agrégations de lignes supplémentaires

Exemple

CREATE PROCEDURE [dbo].[prc-Pivot] (
    @Source varchar(1000),          -- Any Table or Select Statement
    @PvotCol varchar(250),          -- Field name or expression ie. Month(Date)
    @Summaries varchar(250),        -- aggfunction(aggValue)[optionalTitle]
    @GroupBy varchar(250),          -- Optional additional Group By 
    @OtherCols varchar(500) )       -- Optional Group By or aggregates
AS

Set NoCount On
Set Ansi_Warnings Off

Declare @Vals varchar(max),@SQL varchar(max);
Set @Vals = ''
Set @OtherCols= IsNull(', ' + @OtherCols,'')
Set @Source = case when @Source Like 'Select%' then @Source else 'Select * From '+@Source end
Create Table #TempPvot  (Pvot varchar(100))
Insert Into #TempPvot
Exec ('Select Distinct Convert(varchar(100),' + @PvotCol + ') as Pvot FROM (' + @Source + ') A')
Select @Vals = @Vals + ', isnull(' + Replace(Replace(@Summaries,'(','(CASE WHEN ' + @PvotCol + '=''' + Pvot +  ''' THEN '),')[', ' END),0) As [' + Pvot ) From #TempPvot Order by Pvot
Drop Table #TempPvot
Set @SQL = Replace('Select ' + Isnull(@GroupBy,'') + @OtherCols + @Vals + ' From (' + @Source + ') PvtFinal ' + case when Isnull(@GroupBy,'')<>'' then 'Group By ' + @GroupBy + ' Order by ' + @GroupBy else '' end,'Select , ','Select ')
--Print @SQL
Exec (@SQL)


Set NoCount Off
Set Ansi_Warnings on

Ou aussi simple que p>

Exec [prc-Pivot] '#YourTable','Date','sum([Result])[]','Name',null

Retours

entrez la description de l'image ici

La procédure stockée

Exec [prc-Pivot] '#YourTable','Date','sum([Result])[]','Name','count(*)[Records],min(Result)[MinValue],max(Result)[MaxValue]'


1 commentaires

Bingo! Merci beaucoup John. Votre procédure donne les colonnes dont j'avais besoin. De plus, c'est vraiment universel. Pour le paramètre source, j'ai mis l'instruction SELECT avec des conditions WHERE au lieu du nom de la table. Ce sera donc utile pour l'avenir. Tu m'as beaucoup aidé.