2017-05-29 7 views
0
groupe

I ma table par moisComment regrouper par mois, y compris tous les mois?

SELECT TO_CHAR (created, 'YYYY-MM') AS operation, COUNT (id) 
    FROM user_info 
    WHERE created IS NOT NULL 
GROUP BY ROLLUP (TO_CHAR (created, 'YYYY-MM')) 

2015-04 1 
2015-06 10 
2015-08 22 
2015-09 8 
2015-10 13 
2015-12 5 
2016-01 25 
2016-02 37 
2016-03 24 
2016-04 1 
2016-05 1 
2016-06 2 
2016-08 2 
2016-09 7 
2016-10 103 
2016-11 5 
2016-12 2 
2017-04 14 
2017-05 2 
     284 

Mais les dossiers ne couvrent pas tous les mois.
je voudrais la sortie d'inclure tous les mois, avec les disparus affichés dans la sortie avec une valeur par défaut:

2017-01 ... 
2017-02 ... 
2017-03 ZERO 
2017-04 ZERO 
2017-05 ... 
+0

Rechercher * table de calendrier *, il y a beaucoup de questions comme celle-ci sur SO. Vous pouvez trouver l'inspiration sur [cette solution complète] (https://stackoverflow.com/questions/36789953/access-sql-count-number-of-people-group-by-week-number/36792224#36792224) J'ai posté le dernier année, c'est pour Access mais le principe est le même pour tous les SGBDR –

+0

S'il vous plaît montrer un [mcve] avec SQL valide, y compris la clause WHERE, etc. – OldProgrammer

Répondre

1

Oracle a a good array of date manipulation functions. Les deux plus pertinentes pour ce problème sont

  • MONTHS_BETWEEN() qui calcule le nombre de mois entre deux dates
  • ADD_MONTHS() qui incrémente une date par le nombre donné de mois

Nous pouvons combiner ces fonctions générer une table de tous les mois couverts par les enregistrements de votre table. Ensuite, nous utilisons une jointure externe pour joindre de manière conditionnelle les enregistrements de USER_INFO à ce calendrier. Quand aucun enregistrement ne correspondra count(id) sera zéro.

with cte as (
    select max(trunc(created, 'MM')) as max_dt 
     , min(trunc(created, 'MM')) as min_dt 
    from user_info 
) 
, cal as (
    select add_months(min_dt, (level-1)) as mth 
    from cte 
    connect by level <= months_between(max_dt, min_dt) + 1 
) 
select to_char(cal.mth, 'YYYY-MM') as operation 
     , count(id) 
from cal 
    left outer join user_info 
    on trunc(user_info.created, 'mm') = cal.mth 
group by rollup (cal.mth) 
order by 1 
/