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

StackOverflow https://stackoverflow.com/questions/485409

  •  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;
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top