J'ai un tableau simple avec des types, des nombres et des dates:
type | April | May | December ----------------------------- A | 1 | 2 | 0 B | 0 | 0 | 9
Je dois ajouter les nombres en fonction du type. Mais ce qui me pose problème, c'est que la table résultante doit avoir les mois sous forme de colonnes:
type | number | date -------------------- A | 2 | 15-MAY-2015 A | 1 | 15-APR-2015 B | 9 | 03-DEC-2015
Comment puis-je utiliser les noms de mois comme colonnes?
J'ai réussi à obtenir les noms des mois en utilisant cette fonction TO_CHAR(table.date, 'Month') AS month
.
3 Réponses :
Il s'agit d'une option (exemple de données de la ligne 1 à 5):
SQL> with test (type, num, datum) as 2 (select 'A', 2, date '2015-05-15' from dual union all 3 select 'A', 1, date '2015-04-15' from dual union all 4 select 'B', 9, date '2015-12-03' from dual 5 ) 6 select type, 7 max(case when to_char(datum, 'mm') = '04' then num else 0 end) as april, 8 max(case when to_char(datum, 'mm') = '05' then num else 0 end) as may, 9 max(case when to_char(datum, 'mm') = '12' then num else 0 end) as december 10 from test 11 group by type 12 order by type; T APRIL MAY DECEMBER - ---------- ---------- ---------- A 1 2 0 B 0 0 9 SQL>
Salut, cela résout presque mon problème. Le problème est que je dois additionner les valeurs, mais votre code ne remplace le nombre que par num. Désolé, car dans mon exemple, vous ne pouviez pas voir les chiffres ajoutés.
Dans ce cas, au lieu de MAX, utilisez la fonction SOMME.
Vous pouvez utiliser SYS_REFCURSOR
pour une instruction SQL d'agrégation conditionnelle dans une fonction stockée telle que
VAR rc REFCURSOR EXEC :rc := Get_Totals_For_Months; PRINT rc
afin d'utiliser les noms de mois comme colonnes ( sans tenir compte de l'année, probablement restée dans une période d'un an seulement )
puis appelez comme
CREATE OR REPLACE FUNCTION Get_Totals_For_Months RETURN SYS_REFCURSOR IS v_recordset SYS_REFCURSOR; v_sql VARCHAR2(32767); v_cols VARCHAR2(32767); BEGIN SELECT LISTAGG('SUM(CASE WHEN TO_CHAR("date",''mm'') = '''||LPAD(level,2,0)|| ''' THEN "number" END ) AS '||TO_CHAR(TO_DATE(LPAD(level,2,0)||'-01','mm-dd'),'Month'),',') WITHIN GROUP (ORDER BY level) INTO v_cols FROM dual CONNECT BY level <= 12; v_sql := 'SELECT type,'||v_cols|| ' FROM tab GROUP BY type'; OPEN v_recordset FOR v_sql; RETURN v_recordset; END; /
Utilisez PIVOT
:
TYPE | JANUARY | FEBRUARY | MARCH | APRIL | MAY | JUNE | JULY | AUGUST | SEPTEMBER | OCTOBER | NOVEMBER | DECEMBER :--- | ------: | -------: | ----: | ----: | ---: | ---: | ---: | -----: | --------: | ------: | -------: | -------: B | null | null | null | null | null | null | null | null | null | null | null | 9 A | null | null | null | 1 | 2 | null | null | null | null | null | null | null
Lequel, pour les exemples de données:
CREATE TABLE table_name ( type, num, dt ) AS SELECT 'A', 2, DATE '2015-05-15' FROM DUAL UNION ALL SELECT 'A', 1, DATE '2015-04-15' FROM DUAL UNION ALL SELECT 'B', 9, DATE '2015-12-03' FROM DUAL;
Les sorties:
SELECT * FROM ( SELECT type, num, EXTRACT( MONTH FROM dt ) AS month FROM table_name ) PIVOT ( SUM( num ) FOR month IN ( 1 AS January, 2 AS February, 3 AS March, 4 AS April, 5 AS May, 6 AS June, 7 AS July, 8 AS August, 9 AS September, 10 AS October, 11 AS November, 12 AS December ) )
db <> violon ici