28

假设我有一个这样的数据库列“等级”:

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

SQL 中是否有一种不平凡的方式来生成这样的直方图?

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

其中 2 表示第 1 级出现两次,1s 表示第 {2..5} 级出现一次,0 表示第 6 级根本不出现。

我不介意直方图是否每次计数一行。

如果这很重要,那么数据库是由 perl CGI 通过 unixODBC/FreeTDS 访问的 SQL Server。

编辑:感谢您的快速回复!如果不存在不存在的值(如上例中的 6 年级)没有出现也没关系,只要我能确定哪个直方图值属于哪个年级。

4

7 回答 7

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

尚未验证它,但它应该可以工作。但是,它不会显示 6s 等级的计数,因为它根本不存在于表中......

于 2009-01-27T21:45:27.927 回答
14

如果有很多数据点,您还可以像这样将范围分组在一起

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 语句有选择地将值计数到任意 bin 中,然后对它们进行 unpivot以获得包含值的逐行计数

于 2016-12-22T03:09:44.713 回答
7

使用临时表来获取您的缺失值:

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
于 2009-01-27T21:49:24.673 回答
4

Gamecat 对 DISTINCT 的使用对我来说似乎有点奇怪,当我回到办公室时必须尝试一下......

我会这样做的方式虽然相似......

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

为了克服出现 0 次出现数据不足的问题,您可以 LEFT JOIN 到包含所有有效成绩的表中。COUNT(*) 将计算 NULLS,但 COUNT(grade) 不会计算 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
于 2009-01-27T21:47:59.683 回答
4

根据 Shlomo Priymak 的文章How to Quickly Create a Histogram in 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       *
于 2014-09-06T22:58:56.583 回答
2
select Grade, count(Grade)
from MyTable
group by Grade
于 2009-01-27T21:46:16.363 回答
0

我正在构建 Ilya Volodin 上面所做的事情,这应该允许您选择要在结果中组合在一起的等级范围:

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;
于 2015-08-29T23:40:25.557 回答