GROUP BY SQL Server之后的总SUM的百分比

时间:2017-10-24 11:34:51

标签: sql sql-server join sum percentage

我有这些结果:

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

6 个答案:

答案 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. 数据库已更改为SQL Server。
  2. 总数存储为数字而不是字符串。

答案 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;