我有这些结果:
PersonID SUM(PA.Total)
-------------------------
1 75
2 75
3 15
4 15
5 60
6 60
使用如下表格:
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
这些按人分组。现在我要添加一个列,其中每个人的百分比是根据所有总和的总和来计算的。
例如:总和是300,因此我需要这样的结果:
PersonID SUM(PA.Total) Percentage
--------------------------------------
1 75 25%
2 75 25%
3 15 5%
4 15 5%
5 60 20%
6 60 20%
我已经在线查看了代码,并且我已经提出了这样的修复:
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
但我不确定如何将交叉连接合并到连接以及已经组/ sum部分。或者这是否完全沿着正确的方向发展。
任何帮助都会受到赞赏 - SQL小提琴http://sqlfiddle.com/#!9/80f91/2
答案 0 :(得分:14)
您不需要cross join
。只需使用窗口函数:
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;
请注意,此查询不需要JOIN
:
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执行整数除法。我使用十进制数进行这样的计算,因此它们更有意义。
Here是一个SQL小提琴,有两处变化:
答案 1 :(得分:2)
您可以使用公用表表达式...
;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
答案 2 :(得分:1)
请尝试以下代码
;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
结果
PersonID Total Percentage
------------------------------
1 75 25%
2 75 25%
3 15 5%
4 15 5%
5 60 20%
6 60 20%
答案 3 :(得分:1)
就像其他人说的那样,你可以用CTE来解决这个问题,我的有点不同,因为我没有使用CROSS JOIN(没有特殊原因)并做了双CTE。此外,我抛出一个NULLIF以防止可能被零错误(将导致NULL)。
此外,无论何时汇总或执行数学,Package table Total列都应该是数字类型(不是特定的"数字"类型,而是可以容纳numbers的列类型)在列上,这是一个小费,它应该是数字。
;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
答案 4 :(得分:0)
添加到选定的答案中,您可以添加另一个变量来进一步分割%,例如某人的办公室
SELECT PA.PersonID, SUM(PA.Total),PERSONOFFICE,
SUM(PA.Total) * 100.0 / SUM(SUM(PA.Total)) OVER (**PARTITION BY PERSONOFFICE**) AS Percentage
FROM Package PA
GROUP BY PA.PersonID, PERSONOFFICE;
这将由办公室提供总计。
发布为新答案,而不是发表评论,以提高可见度。
答案 5 :(得分:0)
简单
SELECT P.PersonID, SUM(PA.Total),
SUM(PA.Total) * 100.0 / (SELECT SUM(PA.Total) FROM PA)
FROM Person P JOIN
Package PA
ON P.PersonID = PA.PackageFK
GROUP BY P.PersonID;
没有JOIN
SELECT PA.PersonID, SUM(PA.Total),
SUM(PA.Total) * 100.0 / (SELECT SUM(PA.Total) FROM PA)
FROM Package PA
GROUP BY PA.PersonID;