Как вычислить процент с помощью инструкции SQL
у меня есть таблица SQL Server, которая содержит пользователей и их оценки. Для простоты, давайте просто скажем, что есть 2 столбца -name & grade. Таким образом, типичная строка будет называться: "John Doe", Grade:"A".
Я ищу один оператор 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 ввода-вывода").
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.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, чтобы гарантировать, что вычисление происходит с использованием нецелочисленной десятичной, числовой арифметики; см. комментарии и спасибо Гром.)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
в любой версии sql server вы можете использовать переменную для общего количества всех классов следующим образом:
declare @countOfAll decimal(18, 4) select @countOfAll = COUNT(*) from Grades select Grade, COUNT(*) / @countOfAll * 100 from Grades group by Grade
вы можете использовать подвыборку в своем запросе from (непроверенный и не уверен, что быстрее):
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
Comments