То, что вы ищете, это в основном данные для гистограммы .
Вы бы имели возраст (или возрастной диапазон) на оси X и число n (или частоту) на оси Y.
В простейшей форме можно просто посчитать количество каждого отдельного значения возраста, как вы уже описали:
SELECT age, count(*)
FROM tbl
GROUP BY age
Однако, если для оси x слишком много разных значений, может потребоваться создать группы (или кластеры, или сегменты). В вашем случае вы группируете по постоянному диапазону 10.
Мы можем избежать написания строки WHEN ... THEN
для каждого диапазона - их может быть несколько, если речь не идет о возрасте. Вместо этого подход @MatthewFlaschen предпочтительнее по причинам, указанным @ NitinMidha.
Теперь давайте создадим 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 за его подход; Я только объяснил детали.