probablemente se optimizaria utilizando join, pero creo la parte mas pesada es que esta haciendo operaciones con todos los registros en su campo fecha..
eso hace bastante pesado el proceso porque se recorre la tabla completa, registro por registro para aplicarle la funcion, y se deja de utilizar los indices..
Lo mejor es hacer rangos del tipo >= y <= para lo de las fechas.
solo que tu consulta esta algo complicada y no me queda claro que es lo que necesitas...
si la explicar mas a detalle seguro podran ayudarte a replantearla..
Saludos!