Je suis très nouveau pour SQL.
J'ai une table comme celle-ci:
ID | TeamID | UserID | ElementID | PhaseID | Effort
-----------------------------------------------------
1 | 1 | 1 | 3 | 5 | 6.74
2 | 1 | 1 | 3 | 6 | 8.25
3 | 1 | 1 | 4 | 1 | 2.23
4 | 1 | 1 | 4 | 5 | 6.8
5 | 1 | 1 | 4 | 6 | 1.5
Et on m'a dit d'obtenir des données comme celle-ci
ElementID | PhaseID1 | PhaseID5 | PhaseID6
--------------------------------------------
3 | NULL | 6.74 | 8.25
4 | 2.23 | 6.8 | 1.5
Je comprends que je dois utiliser la fonction PIVOT. Mais je ne peux pas comprendre clairement. Ce serait très utile si quelqu'un pouvait l'expliquer dans le cas ci-dessus (ou une alternative le cas échéant).
Un PIVOT
permet de faire pivoter les données d'une colonne en plusieurs colonnes.
Pour votre exemple, voici un pivot STATIC qui signifie que vous codez en dur les colonnes que vous voulez faire pivoter:
create table temp
(
id int,
teamid int,
userid int,
elementid int,
phaseid int,
effort decimal(10, 5)
)
insert into temp values (1,1,1,3,5,6.74)
insert into temp values (2,1,1,3,6,8.25)
insert into temp values (3,1,1,4,1,2.23)
insert into temp values (4,1,1,4,5,6.8)
insert into temp values (5,1,1,4,6,1.5)
select elementid
, [1] as phaseid1
, [5] as phaseid5
, [6] as phaseid6
from
(
select elementid, phaseid, effort
from temp
) x
pivot
(
max(effort)
for phaseid in([1], [5], [6])
)p
Voici un démo SQL avec une version de travail.
Cela peut également être effectué via un PIVOT dynamique dans lequel vous créez la liste de colonnes de manière dynamique et exécutez le PIVOT.
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX);
select @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.phaseid)
FROM temp c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT elementid, ' + @cols + ' from
(
select elementid, phaseid, effort
from temp
) x
pivot
(
max(effort)
for phaseid in (' + @cols + ')
) p '
execute(@query)
Les résultats pour les deux:
ELEMENTID PHASEID1 PHASEID5 PHASEID6
3 Null 6.74 8.25
4 2.23 6.8 1.5
Ce sont l’exemple très basique de pivot.
SQL SERVER - Exemples de tables PIVOT et UNPIVOT
Exemple de lien ci-dessus pour la table de produits:
SELECT PRODUCT, FRED, KATE
FROM (
SELECT CUST, PRODUCT, QTY
FROM Product) up
PIVOT (SUM(QTY) FOR CUST IN (FRED, KATE)) AS pvt
ORDER BY PRODUCT
rend:
PRODUCT FRED KATE
--------------------
BEER 24 12
MILK 3 1
SODA NULL 6
VEG NULL 5
Vous trouverez des exemples similaires dans l'article de blog Tableaux croisés dynamiques dans SQL Server. Un exemple simple
J'étais nouveau dans ce domaine et j'ai créé un article de Nice à ce sujet ... Mon problème était de comprendre comment appliquer correctement l'agrégation et voici mon article: http://jaider.net/posts/1176-pivot-in -sql-serveur-correct-agrégé-résultats /
Dans la solution @bluefeet, il est important de mentionner que elementid
est la colonne clé de votre "invisible" Group By
. En outre, vous pouvez remplacer elementid
ou ajouter d'autres colonnes telles que userid
.
SELECT <non-pivoted column>,
[first pivoted column] AS <column name>,
[second pivoted column] AS <column name>,
...
[last pivoted column] AS <column name>
FROM
(<SELECT query that produces the data>)
AS <alias for the source query>
PIVOT
(
<aggregation function>(<column being aggregated>)
FOR
[<column that contains the values that will become column headers>]
IN ( [first pivoted column], [second pivoted column],
... [last pivoted column])
) AS <alias for the pivot table>
<optional ORDER BY clause>;
USE AdventureWorks2008R2 ;
GO
SELECT DaysToManufacture, AVG(StandardCost) AS AverageCost
FROM Production.Product
GROUP BY DaysToManufacture;
DaysToManufacture AverageCost
0 5.0885
1 223.88
2 359.1082
4 949.4105
-- Pivot table with one row and five columns
SELECT 'AverageCost' AS Cost_Sorted_By_Production_Days,
[0], [1], [2], [3], [4]
FROM
(SELECT DaysToManufacture, StandardCost
FROM Production.Product) AS SourceTable
PIVOT
(
AVG(StandardCost)
FOR DaysToManufacture IN ([0], [1], [2], [3], [4])
) AS PivotTable;
Here is the result set.
Cost_Sorted_By_Production_Days 0 1 2 3 4
AverageCost 5.0885 223.88 359.1082 NULL 949.4105
J'ai quelque chose à ajouter ici dont personne n'a parlé.
La fonction pivot
fonctionne à merveille lorsque la source comporte 3 colonnes: une pour le aggregate
, une pour se répandre sous forme de colonnes avec for
, et une en tant que pivot pour row
Distribution. Dans l'exemple de produit, il s'agit de QTY, CUST, PRODUCT
.
Cependant, si vous avez plus de colonnes dans la source, les résultats seront divisés en plusieurs lignes au lieu d'une ligne par pivot basée sur des valeurs uniques par colonne supplémentaire (comme Group By
ferait une simple requête).
Voir cet exemple, ive a ajouté une colonne timestamp à la table source:
Voyons maintenant son impact:
SELECT CUST, MILK
FROM Product
-- FROM (SELECT CUST, Product, QTY FROM PRODUCT) p
PIVOT (
SUM(QTY) FOR PRODUCT IN (MILK)
) AS pvt
ORDER BY CUST
Pour résoudre ce problème, vous pouvez soit extraire une sous-requête en tant que source, comme tout le monde l’a fait ci-dessus - avec seulement 3 colonnes (cela ne fonctionnera pas toujours pour votre scénario, imaginez si vous avez besoin de mettre un where
condition pour l'horodatage).
La deuxième solution consiste à utiliser un group by
et faites à nouveau la somme des valeurs de la colonne pivotée.
SELECT
CUST,
sum(MILK) t_MILK
FROM Product
PIVOT (
SUM(QTY) FOR PRODUCT IN (MILK)
) AS pvt
GROUP BY CUST
ORDER BY CUST
GO
Pour définir une erreur de compatibilité
utilisez-le avant d'utiliser la fonction de pivot
ALTER DATABASE [dbname] SET COMPATIBILITY_LEVEL = 100