Генерация гистограммы из значений столбца в базе данных

Скажем, у меня есть столбец базы данных 'grade' следующим образом:

|grade|
|    1|
|    2|
|    1|
|    3|
|    4|
|    5|

Существует ли нетривиальный способ в SQL генерировать такую ​​гистограмму?

|2,1,1,1,1,0|

где 2 означает, что класс 1 встречается дважды, средние оценки {2..5} 1s происходят один раз, а 0 означает, что оценка 6 вообще не встречается.

Я не возражаю, если гистограмма - одна строка за счет.

Если это имеет значение, база данных - это SQL Server, доступ к которой осуществляется через Perl CGI через unixODBC/FreeTDS.

EDIT: Спасибо за ваши быстрые ответы! Это нормально, если несуществующие значения (например, класс 6 в приведенном выше примере) не возникают, если я могу определить, какое значение гистограммы принадлежит какому классу.

Ответы

Ответ 1

SELECT COUNT(grade) FROM table GROUP BY grade ORDER BY grade

Не проверял его, но он должен работать. Однако он не будет показывать количество баллов для класса 6s, поскольку он вообще не присутствует в таблице...

Ответ 2

Используйте временную таблицу для получения ваших отсутствующих значений:

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

Ответ 3

Использование Gamecat DISTINCT кажется немного странным для меня, придется попробовать его, когда я вернусь в офис...

То, как я это сделаю, похоже, хотя...

SELECT
    [table].grade        AS [grade],
    COUNT(*)             AS [occurances]
FROM
    [table]
GROUP BY
    [table].grade
ORDER BY
    [table].grade

Чтобы преодолеть нехватку данных, где есть 0 событий, вы можете ВСПОМОГАТЬ JOIN на таблицу, содержащую все допустимые оценки. COUNT (*) будет считать NULLS, но COUNT (класс) не будет считать NULLS.

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

Ответ 4

select Grade, count(Grade)
from MyTable
group by Grade

Ответ 5

Согласно статье Шломо Приймака Как быстро создать гистограмму в 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       *

Ответ 6

Если есть много точек данных, вы также можете группировать группы следующим образом:

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, вам понадобится Кроме того, группа также копирует диапазон в выражение группы.

Ответ 7

Я основываюсь на том, что сделал Илья Володин выше, что должно позволить вам выбрать диапазон оценки, который вы хотите группировать вместе в своем результате:

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;