Question

Disons que j'ai une colonne de "base de données" comme celle-ci:

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

Existe-t-il une méthode non-triviale en SQL pour générer un histogramme comme celui-ci?

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

où 2 signifie que la note 1 a lieu deux fois, les notes moyennes de 1 s {2..5} se produisent une fois et 0 signifie que la note 6 ne se produit pas du tout.

Cela ne me dérange pas si l'histogramme est une ligne par compte.

Si cela compte, la base de données est SQL Server accessible par un CGI perl via unixODBC / FreeTDS.

MODIFIER: Merci pour vos réponses rapides! Cela ne pose pas de problème si des valeurs inexistantes (comme la 6e année dans l'exemple ci-dessus) ne se produisent pas tant que je peux déterminer quelle valeur d'histogramme appartient à quelle année.

Était-ce utile?

La solution

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

Je ne l’ai pas vérifié, mais cela devrait fonctionner. Il ne sera cependant pas pris en compte pour la note 6s, car il n’est pas du tout présent dans le tableau ...

Autres conseils

Utilisez une table temporaire pour obtenir vos valeurs manquantes:

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

S'il y a beaucoup de points de données, vous pouvez également group va ensemble comme ceci:

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

De plus, si vous souhaitez étiqueter toute la gamme, vous pouvez obtenir le plancher et le plafond à l’avance avec 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

Remarque : dans certains moteurs SQL, vous pouvez GROUP BY créer un index de colonne ordinale, mais avec MS SQL, si vous le souhaitez dans l'instruction SELECT, vous devrez groupe également, copiant ainsi la plage dans l’expression de groupe.

Option 2 : vous pouvez utiliser les instructions case pour compter de manière sélective les valeurs dans des bacs arbitraires, puis les dé-balancer pour obtenir un nombre ligne par ligne des valeurs incluses

L’utilisation de DISTINCT par Gamecat me semble un peu étrange, je devrai l’essayer quand je serai de retour au bureau ...

La façon dont je le ferais est similaire mais ...

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

Pour pallier le manque de données où il n’ya pas d’occurrences 0, vous pouvez LEFT JOIN sur une table contenant toutes les notes valides. COUNT (*) comptera NULLS, mais COUNT (grade) ne comptera pas 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

Selon l'article de Shlomo Priymak Comment Créez rapidement un histogramme dans MySQL , vous pouvez utiliser la requête suivante:

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

Qui produira le tableau suivant:

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

Je me base sur ce que Ilya Volodin a fait ci-dessus, qui devrait vous permettre de sélectionner une plage de niveaux que vous souhaitez regrouper dans votre résultat:

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;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top