如何用SQL语句计算百分比

我有一个包含用户及其成绩的SQL Server表。 为了简单起见,我们只是说有2列 – namegrade 。 所以一个典型的行将是名字:“John Doe”,等级:“A”。

我正在寻找一个SQL语句,可以find所有可能的答案的百分比。 (A,B,C等)另外,有没有办法做到这一点,没有定义所有可能的答案(打开文本字段 – 用户可以input“通过/失败”,“没有”等…)

我要找的最后输出是A:5%,B:15%,C:40%等等。

我已经testing了以下,这是行不通的。 gordyii的答案很接近,但在错误的地方增加了100,并且有一些缺失的括号。

 Select Grade, (Count(Grade)* 100 / (Select Count(*) From MyTable)) as Score From MyTable Group By Grade 
  1. 最高效的(使用over())。

     select Grade, count(*) * 100.0 / sum(count(*)) over() from MyTable group by Grade 
  2. 通用(任何SQL版本)。

     select Rate, count(*) * 100.0 / (select count(*) from MyTable) from MyTable group by Rate; 
  3. 使用CTE,效率最低。

     with t(Rate, RateCount) as ( select Rate, count(*) from MyTable group by Rate ) select Rate, RateCount * 100.0/(select sum(RateCount) from t) from t; 

不用单独的CTE来获得总数,你可以使用一个没有“partition by”子句的窗口函数。

如果您正在使用:

 count(*) 

为了得到一个组的计数,你可以使用:

 sum(count(*)) over () 

得到总数。

例如:

 select Grade, 100. * count(*) / sum(count(*)) over () from table group by Grade; 

我的经验往往会更快,但我认为在某些情况下可能会在内部使用临时表(我已经在“set statistics io on”下运行时看到了“Worktable”)。

编辑:我不知道如果我的示例查询是你在找什么,我只是说明窗口function是如何工作的。

你必须计算总分数如果是SQL 2005,你可以使用CTE

  WITH Tot(Total) ( SELECT COUNT(*) FROM table ) SELECT Grade, COUNT(*) / Total * 100 --, CONVERT(VARCHAR, COUNT(*) / Total * 100) + '%' -- With percentage sign --, CONVERT(VARCHAR, ROUND(COUNT(*) / Total * 100, -2)) + '%' -- With Round FROM table GROUP BY Grade 

你需要在成绩栏上分组。 这个查询应该给你几乎所有的数据库。

  Select Grade, CountofGrade / sum(CountofGrade) *100 from ( Select Grade, Count(*) as CountofGrade From Grades Group By Grade) as sub Group by Grade 

你应该指定你正在使用的系统。

我相信这是一个通用的解决scheme,尽pipe我使用IBM Informix Dynamic Server 11.50.FC3进行了testing。 以下查询:

 SELECT grade, ROUND(100.0 * grade_sum / (SELECT COUNT(*) FROM grades), 2) AS pct_of_grades FROM (SELECT grade, COUNT(*) AS grade_sum FROM grades GROUP BY grade ) ORDER BY grade; 

在横向规则下面显示的testing数据上给出以下输出。 ROUND函数可能是DBMS特定的,但其余(可能)不是。 (请注意,我将100更改为100.0,以确保使用非整数进行计算 – DECIMAL,NUMERIC – arithmetic;请参阅评论,感谢Thunder。)

 grade pct_of_grades CHAR(1) DECIMAL(32,2) A 32.26 B 16.13 C 12.90 D 12.90 E 9.68 F 16.13 

 CREATE TABLE grades ( id VARCHAR(10) NOT NULL, grade CHAR(1) NOT NULL CHECK (grade MATCHES '[ABCDEF]') ); INSERT INTO grades VALUES('1001', 'A'); INSERT INTO grades VALUES('1002', 'B'); INSERT INTO grades VALUES('1003', 'F'); INSERT INTO grades VALUES('1004', 'C'); INSERT INTO grades VALUES('1005', 'D'); INSERT INTO grades VALUES('1006', 'A'); INSERT INTO grades VALUES('1007', 'F'); INSERT INTO grades VALUES('1008', 'C'); INSERT INTO grades VALUES('1009', 'A'); INSERT INTO grades VALUES('1010', 'E'); INSERT INTO grades VALUES('1001', 'A'); INSERT INTO grades VALUES('1012', 'F'); INSERT INTO grades VALUES('1013', 'D'); INSERT INTO grades VALUES('1014', 'B'); INSERT INTO grades VALUES('1015', 'E'); INSERT INTO grades VALUES('1016', 'A'); INSERT INTO grades VALUES('1017', 'F'); INSERT INTO grades VALUES('1018', 'B'); INSERT INTO grades VALUES('1019', 'C'); INSERT INTO grades VALUES('1020', 'A'); INSERT INTO grades VALUES('1021', 'A'); INSERT INTO grades VALUES('1022', 'E'); INSERT INTO grades VALUES('1023', 'D'); INSERT INTO grades VALUES('1024', 'B'); INSERT INTO grades VALUES('1025', 'A'); INSERT INTO grades VALUES('1026', 'A'); INSERT INTO grades VALUES('1027', 'D'); INSERT INTO grades VALUES('1028', 'B'); INSERT INTO grades VALUES('1029', 'A'); INSERT INTO grades VALUES('1030', 'C'); INSERT INTO grades VALUES('1031', 'F'); 

以下应该工作

 ID - Key Grade - A,B,C,D... 

编辑:移动* 100并添加1.0以确保它不会做整数除法

 Select Grade, Count(ID) * 100.0 / ((Select Count(ID) From MyTable) * 1.0) From MyTable Group By Grade 

当我需要制定一个百分比时,我只是简单地使用它。

 ROUND(CAST((Numerator * 100.0 / Denominator) AS FLOAT), 2) AS Percentage 

请注意,100.0返回小数,而100自己会将结果四舍五入到最接近的整数,即使使用ROUND()函数!

在任何sql服务器版本中,你都可以使用一个variables作为所有成绩的总和,如下所示:

 declare @countOfAll decimal(18, 4) select @countOfAll = COUNT(*) from Grades select Grade, COUNT(*) / @countOfAll * 100 from Grades group by Grade 

您可以在您的查询中使用子查询(未经testing,不确定哪个更快):

 SELECT Grade, COUNT(*) / TotalRows FROM (SELECT Grade, COUNT(*) As TotalRows FROM myTable) Grades GROUP BY Grade, TotalRows 

要么

 SELECT Grade, SUM(PartialCount) FROM (SELECT Grade, 1/COUNT(*) AS PartialCount FROM myTable) Grades GROUP BY Grade 

要么

 SELECT Grade, GradeCount / SUM(GradeCount) FROM (SELECT Grade, COUNT(*) As GradeCount FROM myTable GROUP BY Grade) Grades 

您也可以使用存储过程(对Firebird语法表示歉意):

 SELECT COUNT(*) FROM myTable INTO :TotalCount; FOR SELECT Grade, COUNT(*) FROM myTable GROUP BY Grade INTO :Grade, :GradeCount DO BEGIN Percent = :GradeCount / :TotalCount; SUSPEND; END 
 SELECT Grade, GradeCount / SUM(GradeCount) FROM (SELECT Grade, COUNT(*) As GradeCount FROM myTable GROUP BY Grade) Grades