Как в данном случае сделать запрос (SQL)?

У меня есть таблица и на её основе нужно составить запрос по условию.

Таблица

Задание: Посчитать количество вводимых дисциплин за каждые 5 лет, начиная с 1990 года.

Подскажите как правильно его составить, возможно пятилетки как то представить? Буду признателен за пример.

Пробовал реализовать через цикл перебора, но мне это решение не понравилось, думаю всё гораздо проще)


Ответы (2 шт):

Автор решения: Дмитрий Бесшапошников

дату делим на пять и группируем по результату деления не учитывая остаток. затем математически вычисляем, как назвать столбец. Вот, накидал решение http://sqlfiddle.com/#!17/28751/2/0

with a as(
select 
  dense_rank() over ( order by round(cast(extract('year' from data) as int)/ 5, 0)) as number_5_year
  ,id
  ,name
  ,data
from table_name
where data >= '01-01-1990'
), b as(
select 
  id,
  concat(cast(1990 + (5*(number_5_year-1)) as varchar), '-', cast(1995 + (5*(number_5_year-1)) as varchar)) as name_5_year
  from a
 )
 select count(*) as count_predmet
   , name_5_year
 from b
 group by name_5_year
 order by name_5_year
→ Ссылка
Автор решения: ValNik

Пример расчета скользящей суммы и скользящей средней за 5 лет.
Используем CTE для создания таблицы всех годов, от первой до последней из имеющихся в исходной таблице. Группируем исходные данные по каждому году для получения количества введенных курсов в этом году. Соединяем и считаем скользящую сумму и среднее.

with recursive years as(
  select min(start_year) yy,max(start_year) endyy 
  from test
  union all
  select yy+1,endyy from years
  where yy<endyy
 )
select yy,coalesce(cnt,0) cnt 
  ,sum(cnt)over(order by yy 
            rows between 4 preceding and current row) rolling_5year_count
  ,avg(coalesce(cnt,0))over(order by yy 
            rows between 4 preceding and current row) rolling_5year_avg
from years
left join 
    (select start_year,count(*) cnt from test group by start_year) yg
        on yg.start_year=years.yy
;

Сумма за каждую пятилетку

select end5y-4 as begin5y,end5y,total_5y_count
from(
   select (ceiling(start_year/5)*5) end5y
     ,count(*) total_5y_count
   from test 
   group by (ceiling(start_year/5)*5)
  )t5y

Здесь выражение (ceiling(start_year/5)*5) - это последний год пятилетки для каждого года, входящего в эту пятилетку

→ Ссылка