Как вычислить процент с помощью инструкции SQL
у меня есть таблица SQL Server, которая содержит пользователей и их оценки. Для простоты давайте просто скажем, что есть 2 столбца -name
& grade
. Таким образом, типичной строкой будет имя: "Джон Доу", класс:"а".
Я ищу один оператор SQL, который найдет проценты всех возможных ответов. (A, B, C и т. д...) Кроме того, есть ли способ сделать это без определения всех возможных ответов (открытое текстовое поле - пользователи могут ввести "pass/fail", "none" и т. д...)
финал выход, который я ищу, - это A: 5%, B: 15%, C: 40% и т. д...
11 ответов
Я проверил следующее, И это работает. Ответ Гордия был близок, но имел умножение 100 в неправильном месте и имел некоторые отсутствующие скобки.
Select Grade, (Count(Grade)* 100 / (Select Count(*) From MyTable)) as Score
From MyTable
Group By Grade
-
наиболее эффективный (использование 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;
вместо использования отдельного CTE для получения общей суммы Вы можете использовать функцию окна без предложения "partition by".
Если вы используете:
count(*)
чтобы получить счетчик для группы, вы можете использовать:
sum(count(*)) over ()
чтобы получить общее количество.
например:
select Grade, 100. * count(*) / sum(count(*)) over ()
from table
group by Grade;
это, как правило, быстрее в моем опыте, но я думаю, что он может внутренне использовать временную таблицу в некоторых случаях (я видел "рабочий стол" при работе с " set statistics io on").
EDIT: Я не уверен, что мой пример запроса-это то, что вы ищете, я просто иллюстрировал, как работают оконные функции.
вы должны рассчитать общее количество оценок Если это 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
вы должны указать систему, которую вы используете.
Я просто использую это, когда мне нужно разработать процент..
ROUND(CAST((Numerator * 100.0 / Denominator) AS FLOAT), 2) AS Percentage
обратите внимание, что 100.0 возвращает десятичные дроби, тогда как 100 самостоятельно округляет результат до ближайшего целого числа, даже с помощью функции ROUND ()!
это, я считаю, общее решение, хотя я тестировал его с помощью IBM Informix Dynamic Server 11.50.ГС3. Следующий запрос:
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;
дает следующие выходные данные по тестовым данным, показанным ниже горизонтального правила. The ROUND
функция может быть специфичной для СУБД, но остальные (возможно) нет. (Обратите внимание, что я изменил 100 на 100.0, чтобы гарантировать, что вычисление происходит с использованием нецелочисленного десятичного, числового арифметического; см. комментарии и спасибо Гром.)
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...
EDIT: переместил * 100
добавил 1.0
чтобы убедиться, что он не выполняет целочисленное деление
Select
Grade, Count(ID) * 100.0 / ((Select Count(ID) From MyTable) * 1.0)
From MyTable
Group By Grade
в любой версии sql server вы можете использовать переменную для общего числа всех классов, как это:
declare @countOfAll decimal(18, 4)
select @countOfAll = COUNT(*) from Grades
select
Grade, COUNT(*) / @countOfAll * 100
from Grades
group by Grade
вы можете использовать подзапроса выборки в запросе (хоть и не уверен, что быстрее):
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