Как рассчитать процент с помощью оператора SQL
У меня есть таблица SQL Server, содержащая пользователей и их оценки. Для простоты просто скажем, что есть 2 столбца - name
и grade
. Таким образом, типичная строка будет Name: "John Doe", Grade: "A".
Я ищу один оператор SQL, который найдет процент всех возможных ответов. (A, B, C и т.д.) Кроме того, есть ли способ сделать это без определения всех возможных ответов (открытое текстовое поле - пользователи могут вводить "pass/fail", "none" и т.д.)
Конечный результат, который я ищу, составляет A: 5%, B: 15%, C: 40% и т.д.
Ответы
Ответ 1
Я тестировал следующее, и это работает. Ответ от gordyii был близок, но имел умножение 100 в неправильном месте и имел некоторые отсутствующие круглые скобки.
Select Grade, (Count(Grade)* 100 / (Select Count(*) From MyTable)) as Score
From MyTable
Group By Grade
Ответ 2
-
Самый эффективный (с использованием функции over()).
select Grade, count(*) * 100.0 / sum(count(*)) over()
from MyTable
group by Grade
-
Универсальная (любая версия SQL).
select Rate, count(*) * 100.0 / (select count(*) from MyTable)
from MyTable
group by Rate;
-
С 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;
Ответ 3
Вместо того, чтобы использовать отдельный CTE для получения общего значения, вы можете использовать функцию окна без предложения "partition by".
Если вы используете:
count(*)
чтобы получить счетчик для группы, вы можете использовать:
sum(count(*)) over ()
чтобы получить общее количество.
Например:
select Grade, 100. * count(*) / sum(count(*)) over ()
from table
group by Grade;
В моем опыте он работает быстрее, но я думаю, что в некоторых случаях он мог бы использовать временную таблицу (я видел "Рабочую таблицу" при работе с "set statistics io on" ).
EDIT:
Я не уверен, что мой примерный запрос - это то, что вы ищете, я просто иллюстрировал работу оконных функций.
Ответ 4
Вы должны рассчитать общее количество оценок
Если это 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
Ответ 5
Вам нужно сгруппировать в поле оценки. Этот запрос должен дать вам то, что вы ищете в почти любой базе данных.
Select Grade, CountofGrade / sum(CountofGrade) *100
from
(
Select Grade, Count(*) as CountofGrade
From Grades
Group By Grade) as sub
Group by Grade
Вы должны указать используемую вами систему.
Ответ 6
Я просто использую это, когда мне нужно проработать процент.
ROUND(CAST((Numerator * 100.0 / Denominator) AS FLOAT), 2) AS Percentage
Обратите внимание, что 100.0 возвращает десятичные числа, тогда как 100 на нем будут округлять результат до ближайшего целого числа, даже с помощью функции ROUND()!
Ответ 7
Следующее должно работать
ID - Key
Grade - A,B,C,D...
EDIT: Перемещено * 100
и добавлено 1.0
, чтобы убедиться, что он не выполняет целочисленное деление
Select
Grade, Count(ID) * 100.0 / ((Select Count(ID) From MyTable) * 1.0)
From MyTable
Group By Grade
Ответ 8
Это, я считаю, общее решение, хотя я тестировал его с помощью 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;
дает следующий результат на тестовых данных, приведенных ниже горизонтального правила. Функция ROUND
может быть специфичной для СУБД, но остальная часть (вероятно) не является. (Обратите внимание, что я изменил 100 на 100.0, чтобы убедиться, что вычисление происходит с использованием нецелого числа - DECIMAL, NUMERIC - арифметика, см. Комментарии и спасибо 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');
Ответ 9
В любой версии sql-сервера вы можете использовать переменную для всех классов, таких как:
declare @countOfAll decimal(18, 4)
select @countOfAll = COUNT(*) from Grades
select
Grade, COUNT(*) / @countOfAll * 100
from Grades
group by Grade
Ответ 10
Вы можете использовать подзапрос в своем запросе (непроверенный и не уверен, что быстрее):
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
Ответ 11
SELECT Grade, GradeCount / SUM(GradeCount)
FROM (SELECT Grade, COUNT(*) As GradeCount
FROM myTable
GROUP BY Grade) Grades