porcentajes - Cómo calcular el porcentaje con una declaración de SQL
porcentajes en postgresql (11)
Tengo una tabla de SQL Server que contiene usuarios y sus calificaciones. En aras de la simplicidad, digamos que hay 2 columnas: name
y grade
. Entonces una fila típica sería Nombre: "John Doe", Grado: "A".
Estoy buscando una declaración de SQL que encuentre los porcentajes de todas las respuestas posibles. (A, B, C, etc.). Además, ¿hay alguna manera de hacerlo sin definir todas las respuestas posibles (campo de texto abierto - los usuarios pueden ingresar ''aprobado / suspendido'', ''ninguno'', etc. ...)
El resultado final que estoy buscando es A: 5%, B: 15%, C: 40%, etc.
El más eficiente (usando más de ()).
select Grade, count(*) * 100.0 / sum(count(*)) over() from MyTable group by Grade
Universal (cualquier versión de SQL).
select Rate, count(*) * 100.0 / (select count(*) from MyTable) from MyTable group by Rate;
Con CTE, el menos eficiente.
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;
Creo que esta es una solución general, aunque la probé utilizando IBM Informix Dynamic Server 11.50.FC3. La siguiente consulta:
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;
da la siguiente salida en los datos de prueba que se muestran debajo de la regla horizontal. La función ROUND
puede ser específica de DBMS, pero el resto (probablemente) no. (Tenga en cuenta que modifiqué 100 a 100.0 para asegurarme de que el cálculo se realiza utilizando valores no enteros - DECIMAL, NUMERIC - aritmética; vea los comentarios y gracias a 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'');
En cualquier versión de servidor sql puede usar una variable para el total de todos los grados como este:
declare @countOfAll decimal(18, 4)
select @countOfAll = COUNT(*) from Grades
select
Grade, COUNT(*) / @countOfAll * 100
from Grades
group by Grade
En lugar de usar un CTE por separado para obtener el total, puede usar una función de ventana sin la cláusula "partición por".
Si estás usando:
count(*)
Para obtener el conteo de un grupo, puede usar:
sum(count(*)) over ()
para obtener la cuenta total
Por ejemplo:
select Grade, 100. * count(*) / sum(count(*)) over ()
from table
group by Grade;
En mi experiencia, tiende a ser más rápido, pero creo que podría usarse internamente una tabla temporal en algunos casos (he visto "Tabla de trabajo" cuando se ejecuta con "establecer estadísticas io en").
EDITAR: No estoy seguro si mi consulta de ejemplo es lo que está buscando, solo estaba ilustrando cómo funcionan las funciones de ventana.
He probado lo siguiente y esto funciona. La respuesta de gordyii estaba cerca pero tenía la multiplicación de 100 en el lugar equivocado y tenía algunos paréntesis faltantes.
Select Grade, (Count(Grade)* 100 / (Select Count(*) From MyTable)) as Score
From MyTable
Group By Grade
Lo siguiente debería funcionar
ID - Key
Grade - A,B,C,D...
EDITAR: movió el * 100
y agregó el 1.0
para asegurarse de que no haga división entera
Select
Grade, Count(ID) * 100.0 / ((Select Count(ID) From MyTable) * 1.0)
From MyTable
Group By Grade
Necesita agrupar en el campo de calificación. Esta consulta debería darle lo que busca en prácticamente cualquier base de datos.
Select Grade, CountofGrade / sum(CountofGrade) *100
from
(
Select Grade, Count(*) as CountofGrade
From Grades
Group By Grade) as sub
Group by Grade
Debe especificar el sistema que está usando.
Puede usar una subselección en su consulta de (no comprobado y no está seguro, que es más rápido):
SELECT Grade, COUNT(*) / TotalRows
FROM (SELECT Grade, COUNT(*) As TotalRows
FROM myTable) Grades
GROUP BY Grade, TotalRows
O
SELECT Grade, SUM(PartialCount)
FROM (SELECT Grade, 1/COUNT(*) AS PartialCount
FROM myTable) Grades
GROUP BY Grade
O
SELECT Grade, GradeCount / SUM(GradeCount)
FROM (SELECT Grade, COUNT(*) As GradeCount
FROM myTable
GROUP BY Grade) Grades
También puede usar un procedimiento almacenado (disculpas por la sintaxis de 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
Simplemente uso esto cuando necesito calcular un porcentaje.
ROUND(CAST((Numerator * 100.0 / Denominator) AS FLOAT), 2) AS Percentage
Tenga en cuenta que 100.0 devuelve decimales, mientras que 100 por sí solo redondeará el resultado al número entero más cercano, incluso con la función ROUND ().
Tienes que calcular el total de calificaciones Si es SQL 2005 puedes usar 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, GradeCount / SUM(GradeCount)
FROM (SELECT Grade, COUNT(*) As GradeCount
FROM myTable
GROUP BY Grade) Grades