Требуется количество диапазонов в sql-запросе

У меня проблема с деталями в http://sqlfiddle.com/#!3/8e018/1

У меня есть таблица членов с отметками всех учеников. Я пытаюсь получить счет всех студентов в диапазонах, таких как

0-9 = количество учеников 9,

10 -19 = количество учеников 0 и т.д. до 100.

Плюс, если какое-то тело может указать на хороший учебник по операторам case, будет очень хорошо

Ответы даны в порядке. но мои диапазоны фиксированы. я должен также показать 0, если нет кандидата Это основное отличие моего вопроса. например, у меня есть также категория.

Ответ 1

Вам не нужен оператор CASE. Вы можете группировать результат целочисленного деления.

SELECT 10 * ( marks / 10 )     AS start_range,
       10 * ( marks / 10 ) + 9 AS end_range,
       count(*)                AS COUNT
FROM   testTable
GROUP  BY marks / 10 

Это приведет к группировке

0  -  9
10 - 19
/* ...*/
90 - 99
100 - 109

Если вы не хотите, чтобы 100 находился в диапазоне самостоятельно (как единственное возможное значение в конечном диапазоне), вам нужно более четко определить требования.

Чтобы включить диапазоны all, вы можете использовать

SELECT CAST(10 * ( G.Grp ) AS VARCHAR(3)) + '-' 
                          + CAST(10 * ( G.Grp ) + 9 AS VARCHAR(3)) AS range,
       count(T.id)                                                 AS Count
FROM   (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) G(Grp)
       LEFT JOIN [dbo].[testTable] T
         ON G.Grp = T.marks / 10
GROUP  BY G.Grp 

SQL Fiddle

Ответ 2

Попробуйте что-то вроде:

SELECT CASE
        WHEN marks IS NULL THEN 'Unknown'
        WHEN marks <= 9 THEN '0-9'
        WHEN marks <= 19 THEN '10-19'
        WHEN marks <= 29 THEN '20-29'
        WHEN marks <= 39 THEN '30-39'
        WHEN marks <= 49 THEN '40-49'
        WHEN marks <= 59 THEN '50-59'
        WHEN marks <= 69 THEN '60-69'
        WHEN marks <= 79 THEN '70-79'
        WHEN marks <= 89 THEN '80-89'
        WHEN marks <= 100 THEN '90-100'
        ELSE 'Over 100'
    END "Bucket",
    COUNT(*) "Number of results"
FROM
    testTable
GROUP BY CASE
        WHEN marks IS NULL THEN 'Unknown'
        WHEN marks <= 9 THEN '0-9'
        WHEN marks <= 19 THEN '10-19'
        WHEN marks <= 29 THEN '20-29'
        WHEN marks <= 39 THEN '30-39'
        WHEN marks <= 49 THEN '40-49'
        WHEN marks <= 59 THEN '50-59'
        WHEN marks <= 69 THEN '60-69'
        WHEN marks <= 79 THEN '70-79'
        WHEN marks <= 89 THEN '80-89'
        WHEN marks <= 100 THEN '90-100'
        ELSE 'Over 100'
    END
ORDER BY
    MIN(marks);

Чтобы объяснить инструкцию CASE здесь (насколько я могу, лучше, люди могут редактировать), мне всегда нравится вводить параметр NULL, поскольку иногда он может ловить ошибки в вашем запросе. Оставшиеся WHEN заявления должны быть понятными, и вы можете использовать их в соответствии с вашими потребностями. Имя "Bucket" - это именно то, что ваш столбец будет вызываться в конечном выпуске, поэтому вы можете изменить это, как хотите. Второй столбец должен быть агрегированным запросом, например COUNT, чтобы оператор CASE имел смысл.

Вы должны повторить оператор CASE, за исключением вашего имени для него, в инструкции GROUP BY.

Ответ 3

Если вам нужны и пустые диапазоны (предположим), попробуйте это:

;WITH Ranges
AS
(
  SELECT 0 n
  UNION ALL
  SELECT n + 1 FROM Ranges
  WHERE n < 9
)
SELECT CAST((n*10) as VARCHAR) + ' - ' + CAST((n*10 + 9) as VARCHAR) [Range], COUNT(marks) Cnt FROM Ranges
  LEFT JOIN [testTable] T
    ON marks >= (n*10) AND marks <= (n*10 + 9)
GROUP BY n*10, n*10 + 9

SQL FIDDLE DEMO