Генерация гистограммы на основе значений столбцов в базе данных
-
20-08-2019 - |
Вопрос
Допустим, у меня есть столбец базы данных "оценка", подобный этому:
|grade|
| 1|
| 2|
| 1|
| 3|
| 4|
| 5|
Есть ли в SQL нетривиальный способ сгенерировать подобную гистограмму?
|2,1,1,1,1,0|
где 2 означает, что оценка 1 встречается дважды, 1s означает, что оценки {2..5} встречаются один раз, а 0 означает, что оценка 6 не встречается вообще.
Я не возражаю, если гистограмма будет состоять из одной строки на счетчик.
Если это имеет значение, база данных - это SQL Server, доступ к которому осуществляется CGI на perl через unixODBC / FreeTDS.
Редактировать: Спасибо за ваши быстрые ответы!Ничего страшного, если несуществующие значения (например, класс 6 в примере выше) не встречаются до тех пор, пока я могу определить, какое значение гистограммы относится к какому классу.
Решение
SELECT COUNT(grade) FROM table GROUP BY grade ORDER BY grade
Не проверял это, но это должно сработать.Однако он не будет показывать количество для класса 6s, поскольку его вообще нет в таблице...
Другие советы
Используйте временную таблицу, чтобы получить недостающие значения:
CREATE TABLE #tmp(num int)
DECLARE @num int
SET @num = 0
WHILE @num < 10
BEGIN
INSERT #tmp @num
SET @num = @num + 1
END
SELECT t.num as [Grade], count(g.Grade) FROM gradeTable g
RIGHT JOIN #tmp t on g.Grade = t.num
GROUP by t.num
ORDER BY 1
Если имеется много точек данных, вы также можете группируйте диапазоны вместе вот так:
SELECT FLOOR(grade/5.00)*5 As Grade,
COUNT(*) AS [Grade Count]
FROM TableName
GROUP BY FLOOR(Grade/5.00)*5
ORDER BY 1
Кроме того, если вы хотите маркировать весь ассортимент, вы можете заранее оформить пол и потолок с помощью CTE.
With GradeRanges As (
SELECT FLOOR(Score/5.00)*5 As GradeFloor,
FLOOR(Score/5.00)*5 + 4 As GradeCeiling
FROM TableName
)
SELECT GradeFloor,
CONCAT(GradeFloor, ' to ', GradeCeiling) AS GradeRange,
COUNT(*) AS [Grade Count]
FROM GradeRanges
GROUP BY GradeFloor, CONCAT(GradeFloor, ' to ', GradeCeiling)
ORDER BY GradeFloor
Примечание:В некоторых движках SQL вы можете GROUP BY
порядковый индекс столбца, но с MS SQL, если вы хотите, чтобы он был в SELECT
оператор, вам также нужно будет сгруппировать по нему, следовательно, также скопировать диапазон в групповое выражение.
Вариант 2:Вы могли бы использовать операторы case для выборочного подсчета значений в произвольные ячейки и последующего их отключения чтобы получить количество включенных значений по строкам
Использование Gamecat DISTINCT кажется мне немного странным, придется попробовать это, когда я вернусь в офис...
Хотя способ, которым я бы это сделал, похож...
SELECT
[table].grade AS [grade],
COUNT(*) AS [occurances]
FROM
[table]
GROUP BY
[table].grade
ORDER BY
[table].grade
Чтобы устранить нехватку данных при наличии 0 совпадений, вы можете включить ЛЕВОЕ СОЕДИНЕНИЕ в таблицу, содержащую все допустимые оценки.COUNT(*) будет подсчитывать нули, но COUNT(grade) не будет подсчитывать НУЛИ.
DECLARE @grades TABLE (
val INT
)
INSERT INTO @grades VALUES (1)
INSERT INTO @grades VALUES (2)
INSERT INTO @grades VALUES (3)
INSERT INTO @grades VALUES (4)
INSERT INTO @grades VALUES (5)
INSERT INTO @grades VALUES (6)
SELECT
[grades].val AS [grade],
COUNT([table].grade) AS [occurances]
FROM
@grades AS [grades]
LEFT JOIN
[table]
ON [table].grade = [grades].val
GROUP BY
[grades].val
ORDER BY
[grades].val
select Grade, count(Grade)
from MyTable
group by Grade
Согласно статье Шломо Приймака Как быстро создать гистограмму в MySQL, вы можете использовать следующий запрос:
SELECT grade,
COUNT(\*) AS 'Count',
RPAD('', COUNT(\*), '*') AS 'Bar'
FROM grades
GROUP BY grade
Который приведет к следующей таблице:
grade Count Bar
1 2 **
2 1 *
3 1 *
4 1 *
5 1 *
Я основываюсь на том, что Илья Володин сделал выше, это должно позволить вам выбрать диапазон оценок, которые вы хотите сгруппировать в своем результате:
DECLARE @cnt INT = 0;
WHILE @cnt < 100 -- Set max value
BEGIN
SELECT @cnt,COUNT(fe) FROM dbo.GEODATA_CB where fe >= @cnt-0.999 and fe <= @cnt+0.999 -- set tolerance
SET @cnt = @cnt + 1; -- set step
END;