您要查找的基本上是histogram 的数据。
x 轴为年龄(或年龄范围),y 轴为计数 n(或频率)。
在最简单的形式中,可以像您已经描述的那样简单地计算每个不同年龄值的数量:
SELECT age, count(*)
FROM tbl
GROUP BY age
但是,当 x 轴有太多不同的值时,可能需要创建组(或集群或存储桶)。在您的情况下,您按 10 的恒定范围分组。
我们可以避免为每个范围编写 WHEN ... THEN 行 - 如果不是关于年龄,可能会有数百个。相反,由于@NitinMidha 提到的原因,@MatthewFlaschen 的方法更可取。
现在让我们构建 SQL...
首先,我们需要将年龄分成 10 个范围组,如下所示:
这可以通过将年龄列除以10然后计算结果的FLOOR来实现:
FLOOR(age/10)
"FLOOR 返回等于或小于 n 的最大整数"
http://docs.oracle.com/cd/E11882_01/server.112/e26088/functions067.htm#SQLRF00643
然后我们使用原始 SQL 并将 age 替换为该表达式:
SELECT FLOOR(age/10), count(*)
FROM tbl
GROUP BY FLOOR(age/10)
这没关系,但我们还看不到范围。相反,我们只看到计算出的底值0, 1, 2 ... n。
要获得实际的下限,我们需要再次将其乘以 10,从而得到0, 10, 20 ... n:
FLOOR(age/10) * 10
我们还需要每个范围的上限 bound + 10 - 1 或
FLOOR(age/10) * 10 + 10 - 1
最后,我们将两者连接成这样的字符串:
TO_CHAR(FLOOR(age/10) * 10) || '-' || TO_CHAR(FLOOR(age/10) * 10 + 10 - 1)
这会创建'0-9', '10-19', '20-29' 等。
现在我们的 SQL 看起来像这样:
SELECT
TO_CHAR(FLOOR(age/10) * 10) || ' - ' || TO_CHAR(FLOOR(age/10) * 10 + 10 - 1),
COUNT(*)
FROM tbl
GROUP BY FLOOR(age/10)
最后,应用一个顺序和漂亮的列别名:
SELECT
TO_CHAR(FLOOR(age/10) * 10) || ' - ' || TO_CHAR(FLOOR(age/10) * 10 + 10 - 1) AS range,
COUNT(*) AS frequency
FROM tbl
GROUP BY FLOOR(age/10)
ORDER BY FLOOR(age/10)
但是,在更复杂的场景中,这些范围可能不会被分组为大小为 10 的恒定块,但需要动态聚类。
Oracle 包含更高级的直方图函数,请参阅http://docs.oracle.com/cd/E16655_01/server.121/e15858/tgsql_histo.htm#TGSQL366
感谢@MatthewFlaschen 的方法;我只解释了细节。