Pregunta

Digamos que tengo una columna de base de datos 'calificación' como esta:

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

¿Existe una forma no trivial en SQL para generar un histograma como este?

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

donde 2 significa que el grado 1 ocurre dos veces, el 1s significa que los grados {2..5} ocurren una vez y 0 significa que el grado 6 no ocurre en absoluto.

No me importa si el histograma es una fila por conteo.

Si eso es importante, la base de datos es SQL Server a la que accede un CGI perl a través de unixODBC / FreeTDS.

EDITAR: ¡Gracias por sus respuestas rápidas! Está bien si los valores no existentes (como el grado 6 en el ejemplo anterior) no ocurren siempre que pueda distinguir qué valor de histograma pertenece a qué grado.

¿Fue útil?

Solución

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

No lo he verificado, pero debería funcionar. Sin embargo, no mostrará el recuento para el grado 6, ya que no está presente en la tabla en absoluto ...

Otros consejos

Use una tabla temporal para obtener sus valores faltantes:

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

Si hay muchos puntos de datos, también puede grupos de grupos juntos así:

SELECT FLOOR(grade/5.00)*5 As Grade, 
       COUNT(*) AS [Grade Count]
FROM TableName
GROUP BY FLOOR(Grade/5.00)*5
ORDER BY 1

Además, si desea etiquetar la gama completa, puede obtener el piso y el techo con anticipación con un 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

Nota : en algunos motores SQL, puede GROUP BY un índice de columna ordinal, pero con MS SQL, si lo desea en la declaración SELECT, necesitará agrupe también, por lo tanto, copie el Rango en la Expresión de grupo también.

Opción 2 : puede usar declaraciones de casos para contar selectivamente los valores en contenedores arbitrarios y luego desunirlos para obtener un recuento fila por fila de los valores incluidos

El uso de DISTINCT por parte de Gamecat me parece un poco extraño, tendré que probarlo cuando vuelva a la oficina ...

La forma en que lo haría es similar ...

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

Para superar la falta de datos donde hay 0 ocurrencias, puede IZQUIERDA UNIRSE a una tabla que contenga todas las calificaciones válidas. COUNT (*) contará NULLS, pero COUNT (grade) no contará 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
select Grade, count(Grade)
from MyTable
group by Grade

Según el artículo de Shlomo Priymak Cómo Cree rápidamente un histograma en MySQL , puede usar la siguiente consulta:

SELECT grade, 
       COUNT(\*) AS 'Count',
       RPAD('', COUNT(\*), '*') AS 'Bar' 
FROM grades 
GROUP BY grade

Que producirá la siguiente tabla:

grade   Count   Bar
1       2       **
2       1       *
3       1       *
4       1       *
5       1       *

Estoy construyendo sobre lo que Ilya Volodin hizo anteriormente, que debería permitirle seleccionar un rango de calificación que desea agrupar en su resultado:

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;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top