Como no trabajo con Store Procedures, te hago una propuesta con la creación de una tabla temporal. Yo trabajo en MysQL y si lanzas esto:
Código sql:
Ver originalCREATE TEMPORARY TABLE tmp engine = memory SELECT YEAR(fecha_compra) año, MONTH(fecha_compra) mes FROM producto UNION DISTINCT SELECT YEAR(fecha_alta), MONTH(fecha_alta) FROM usuarios ORDER BY año, mes;
SELECT * FROM tmp;
SELECT tmp.año,
CASE WHEN tmp.mes =1
THEN "enero"
WHEN tmp.mes =2
THEN "febrero"
WHEN tmp.mes =3
THEN "marzo"
WHEN tmp.mes =4
THEN "abril"
WHEN tmp.mes =5
THEN "mayo"
WHEN tmp.mes =6
THEN "junio"
WHEN tmp.mes =7
THEN "julio"
WHEN tmp.mes =8
THEN "agosto"
WHEN tmp.mes =9
THEN "septiembre"
WHEN tmp.mes =10
THEN "octubre"
WHEN tmp.mes =11
THEN "noviembre"
WHEN tmp.mes =12
THEN "diciembre"
ELSE "esto no es un mes"
END AS mes, IFNULL( t1.totalp, 0 ) AS compras, IFNULL( t2.totalus, 0 ) AS altas
FROM tmp
LEFT JOIN (
SELECT YEAR( fecha_compra ) anyo, MONTH( fecha_compra ) mes, COUNT( * ) totalp
FROM producto
GROUP BY YEAR( fecha_compra ) , MONTH( fecha_compra )
)t1 ON tmp.año = t1.anyo
AND tmp.mes = t1.mes
LEFT JOIN (
SELECT YEAR( fecha_alta ) anyo, MONTH( fecha_alta ) mes, COUNT( * ) totalus
FROM usuarios
GROUP BY YEAR( fecha_alta ) , MONTH( fecha_alta )
)t2 ON tmp.año = t2.anyo
AND tmp.mes = t2.mes
ORDER BY tmp.año, tmp.mes
A mí me ha funcionado en un MySQL 5.0. Creo una tabla temporal que cargo con los datos de año y mes de las otras tablas, con union distinct para evitar las repeticiones de meses; luego hago mediante left join las uniones.
Respecto a lo otro, es decir, a que aparecieran todos los meses, insisto en que tendrías que hacerlo con programación.