如何使用SQL语句计算百分比

Ale*_*lex 158 sql t-sql sql-server

我有一个包含用户及其成绩的SQL Server表.为简单起见,我们只想说有2列 - name&grade.所以一个典型的行是Name:"John Doe",等级:"A".

我正在寻找一个SQL语句,它将找到所有可能答案的百分比.(A,B,C等......)另外,有没有办法在没有定义所有可能的答案的情况下这样做(开放文本字段 - 用户可以输入'通过/失败','无'等...)

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

Jas*_*son 213

我测试了以下内容,这确实有效.gordyii的答案很接近但在错误的地方乘以100并且有一些缺失的括号.

Select Grade, (Count(Grade)* 100 / (Select Count(*) From MyTable)) as Score
From MyTable
Group By Grade
Run Code Online (Sandbox Code Playgroud)

  • 这给出了整数的结果.结果的数量不等于100. (20认同)
  • @Thunder你可以改变100到100.0的十进制值. (14认同)
  • 不是最有效的,因为表将被扫描两次.如果引用了多个表,查询也不会那么简单. (10认同)
  • @ Digitalsa1nt(100*2)/ 4 = 50,(2/4)*100 = 50只要枚举器是被乘的部分.由于SQL语句的优先级,它将是相同的.但是,由于数据类型如果使用100,你仍然可以将结果四舍五入到你想要的%0,如果你把它放在除法运算之后,你必须确保转换为可以处理的数据类型小数位,否则你将得到100或0,而不是实际的百分比 (4认同)

Ale*_*Aza 199

  1. 效率最高(使用over()).

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

    select Grade, count(*) * 100.0 / (select count(*) from MyTable)
    from MyTable
    group by Grade;
    
    Run Code Online (Sandbox Code Playgroud)
  3. 使用CTE,效率最低.

    with t(Grade, GradeCount) 
    as 
    ( 
        select Grade, count(*) 
        from MyTable
        group by Grade
    )
    select Grade, GradeCount * 100.0/(select sum(GradeCount) from t)
    from t;
    
    Run Code Online (Sandbox Code Playgroud)

  • over()在我的SQL Server 2008上完美运行,我做了数学确认.为了将其四舍五入到小数点后两位,我使用了CAST(count(*)*100.0/sum(count(*))over()AS DECIMAL(18,2)).谢谢你的帖子! (12认同)
  • 如果您在100乘法上溢出(例如,将表达式转换为数据类型int_的_Arithmetic溢出错误),请将其替换为分母中的除法:`cast((count(*)/(sum(count(*))over()/ 100))作为DECIMAL(18,2))作为百分比 (3认同)
  • @AS91,因为在分割操作之后,强制转换为十进制.如果你留下一个int(100),除以另一个int也会产生一个int,这会使结果四舍五入.这就是为什么诀窍总是在实际除法之前强制对被除数进行强制转换(你可以乘以像1.0这样的文字小数或者转换/转换) (2认同)

Joh*_*ibb 38

您可以使用不带"partition by"子句的窗口函数,而不是使用单独的CTE来获取总数.

如果您正在使用:

count(*)
Run Code Online (Sandbox Code Playgroud)

要获得组的计数,您可以使用:

sum(count(*)) over ()
Run Code Online (Sandbox Code Playgroud)

得到总数.

例如:

select Grade, 100. * count(*) / sum(count(*)) over ()
from table
group by Grade;
Run Code Online (Sandbox Code Playgroud)

根据我的经验,它往往更快,但我认为在某些情况下它可能会在内部使用临时表(我在运行"set statistics io on"时看到了"工作表").

编辑: 我不确定我的示例查询是否是您正在寻找的,我只是说明了窗口函数的工作原理.

  • 实际上,查询中的“COUNT(*) OVER ()”将返回一个完全不相关的数字(具体来说,*分组*结果集的行数)。您应该使用“SUM(COUNT(*)) OVER ()”来代替。 (3认同)

Jho*_*re- 9

您必须计算成绩总数如果是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
Run Code Online (Sandbox Code Playgroud)


Jer*_*emy 9

您需要在成绩字段上进行分组.这个查询应该可以在几乎任何数据库中为您提供所需的内容.

    Select Grade, CountofGrade / sum(CountofGrade) *100 
    from
    (
    Select Grade, Count(*) as CountofGrade
    From Grades
    Group By Grade) as sub
    Group by Grade
Run Code Online (Sandbox Code Playgroud)

您应该指定您正在使用的系统.

  • 由于你在外部选择中有一个聚合('sum(CountofGrade)'),你也不需要group by子句吗?在标准SQL中,我认为您可以使用'/(SELECT COUNT(*)FROM Grades)'来获得总计. (2认同)

Fan*_*o68 8

我只需要使用它,我需要计算一个百分比..

ROUND(CAST((Numerator * 100.0 / Denominator) AS FLOAT), 2) AS Percentage
Run Code Online (Sandbox Code Playgroud)

需要注意的是100.0返回小数,而100在它自己将结果四舍五入到最接近的整数,甚至与ROUND()函数!


Gor*_*yII 6

以下应该有效

ID - Key
Grade - A,B,C,D...
Run Code Online (Sandbox Code Playgroud)

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

Select 
   Grade, Count(ID) * 100.0 / ((Select Count(ID) From MyTable) * 1.0)
From MyTable
Group By Grade
Run Code Online (Sandbox Code Playgroud)


Jon*_*ler 5

我相信这是一个通用解决方案,尽管我使用IBM Informix Dynamic Server 11.50.FC3对其进行了测试.以下查询:

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;
Run Code Online (Sandbox Code Playgroud)

在水平线下面显示的测试数据上给出以下输出.该ROUND函数可能是DBMS特定的,但其余(可能)不是.(注意,我将100更改为100.0以确保使用非整数进行计算 - DECIMAL,NUMERIC - 算术;请参阅注释,并感谢迅雷.)

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
Run Code Online (Sandbox Code Playgroud)
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');
Run Code Online (Sandbox Code Playgroud)