J'ai ces résultats:
PersonID SUM(PA.Total)
-------------------------
1 75
2 75
3 15
4 15
5 60
6 60
Avec la table comme:
PersonID Total
------------------
1 50
2 50
3 10
4 10
5 40
6 40
1 25
2 25
3 5
4 5
5 20
6 20
Ceux-ci sont regroupés par personne. Maintenant, je cherche à ajouter une colonne avec les pourcentages pour chaque personne calculée à partir du total de toutes leurs sommes.
Par exemple: la somme totale est 300, et j’ai donc besoin d’un résultat comme celui-ci:
PersonID SUM(PA.Total) Percentage
--------------------------------------
1 75 25%
2 75 25%
3 15 5%
4 15 5%
5 60 20%
6 60 20%
J'ai examiné le code en ligne et j'ai trouvé une solution comme celle-ci:
SELECT
P.PersonID, SUM(PA.Total)
SUM(PA.Total) * 100 / [p] AS 'Percentage'
FROM
Person P
JOIN
Package PA ON P.PersonID = PA.PackageFK
CROSS JOIN
(SELECT SUM(PA.[Total]) AS [p]
FROM Package PA) t
GROUP BY
P.PersonID
Mais je ne sais pas comment incorporer la jointure croisée dans la jointure ainsi que la section déjà groupée/somme. Ou si cela va tout à fait dans le bon sens.
Toute aide serait la bienvenue - SQL fiddle http://sqlfiddle.com/#!9/80f91/2
Vous n'avez pas besoin d'un cross join
. Il suffit d'utiliser les fonctions de la fenêtre:
SELECT P.PersonID, SUM(PA.Total),
SUM(PA.Total) * 100.0 / SUM(SUM(PA.Total)) OVER () AS Percentage
FROM Person P JOIN
Package PA
ON P.PersonID = PA.PackageFK
GROUP BY P.PersonID;
Notez que vous n'avez pas besoin de la variable JOIN
pour cette requête:
SELECT PA.PersonID, SUM(PA.Total),
SUM(PA.Total) * 100.0 / SUM(SUM(PA.Total)) OVER () AS Percentage
FROM Package PA
GROUP BY PA.PersonID;
SQL Server effectue une division entière. Je fais de tels calculs en utilisant des nombres décimaux pour qu'ils aient plus de sens.
Ici est un violon SQL, avec deux modifications:
Vous pouvez utiliser Common table Expression ...
;with cte as(
select P.PersonID,SUM(cast(PA.Total as int))Total from Package PA join Person P on P.PersonID = PA.PackageFK GROUP BY P.PersonID
)
select PersonId,Total,cast (Total * 100 / t.GrandTotal as varchar) + '%' [Percentage] from cte cross join(select SUM(cast(Total as int)) as GrandTotal from Package)t
Comme les autres l'ont dit, vous pouvez utiliser le CTE pour résoudre le problème. Le mien est un peu différent en ce sens que je n'ai pas utilisé de CROSS JOIN (pas de raison particulière) et que j'ai fait un double CTE. De plus, j'ai jeté un NULLIF dans pour éviter les erreurs possibles de division par zéro (le résultat sera NULL).
En outre, la colonne Total de la table de packages doit être un type numérique (pas le type spécifique "numérique", mais un type de colonne pouvant contenir nombres ), chaque fois que vous faites la somme ou que vous effectuez des calculs sur une colonne. hors il devrait être numérique.
;WITH PersonTotals AS
(
SELECT P.PersonID, SUM(CAST(PA.Total AS MONEY)) Total
FROM Person P
JOIN Package PA ON P.PersonID = PA.PackageFK
GROUP BY P.PersonID
),
GrandTotal AS
(
SELECT SUM(PT.Total) Total
FROM PersonTotals PT
)
SELECT PT.*, (PT.Total / NULLIF((SELECT Total From GrandTotal),0)) * 100 Percentage
FROM PersonTotals PT
Essayez ce code ci-dessous
;With cte(PersonID ,Total)
AS
(
SELECT 1 ,75 UNION ALL
SELECT 2 ,75 UNION ALL
SELECT 3 ,15 UNION ALL
SELECT 4 ,15 UNION ALL
SELECT 5 ,60 UNION ALL
SELECT 6 ,60
)
SELECT PersonID,
Total,
CAST(CAST((MAX(total)OVER(partition BY personid ORDER BY total)*100.0/
MaxSum) AS INT)AS VARCHAR(5))+ '%' AS Percentage
FROM (SELECT personid,
total,
stotal,
Max(stotal)
OVER(
ORDER BY stotal DESC) AS MaxSum
FROM (SELECT personid,
total,
Sum(total)
OVER(
ORDER BY personid) AS STotal
FROM Cte)dt
GROUP BY dt.personid,
dt.total,
dt.stotal)dt2
ORDER BY dt2.personid ASC
Résultat
PersonID Total Percentage
------------------------------
1 75 25%
2 75 25%
3 15 5%
4 15 5%
5 60 20%
6 60 20%