Начните с генерации месяцев.Тогда я думаю, что коррелированные подзапросы - это простой способ выполнить вычисления:
select v.mon,
(select count(*)
from mytable t
where to_char(date1, 'mon') = v.mon
) as date1,
(select count(*)
from mytable t
where to_char(date2, 'mon') = v.mon
) as date2,
(select count(*)
from mytable t
where to_char(date3, 'mon') = v.mon
) as date3
from (values ('jun', 6), ('may', 5), ('apr', 4)
) v(mon, mm)
order by mm desc;
РЕДАКТИРОВАТЬ:
Хотя приведенное выше должно быть довольно разумным, следующие могут иметь лучшую производительность:
select mon, sum( (which = 1)::int ) as date1, sum( (which = 2)::int ) as date2,
sum( (which = 3)::int ) as date3
from t cross join lateral
(values (1, to_char(date1, 'mon'), extract(month from date1)),
(2, to_char(date2, 'mon'), extract(month from date2)),
(3, to_char(date3, 'mon'), extract(month from date3))
) v(which, mon, mm)
group by mon, mm
order by mm desc;
Здесь - тестер.