Pienso que tu primera consulta que expones sería correcto para el fin que propones :
Código SQL
[-]Select a.categoria,
(Select sum(debe) from caja t1
where t1.categoria = a.categoria and year(t1.fecha) = 2008) as egreso,
(Select sum(haber) from caja t2
where t2.categoria = a.categoria and year(t2.fecha) = 2008) as ingreso
from parapersonales a
Entonces .... por qué no planteas tu segunda consulta de la misma manera ?

, es decir, no creo que hiciera falta ningún Join
Código SQL
[-]Select a.categoria,
(Select sum(debe) from caja t1
where t1.categoria = a.categoria and year(t1.fecha) = 2008) as egreso2008,
(Select sum(haber) from caja t2
where t2.categoria = a.categoria and year(t2.fecha) = 2008) as ingreso2008,
(Select sum(debe) from caja u1
where u1.categoria = a.categoria and year(u1.fecha) = 2007) as egreso2007,
(Select sum(haber) from caja u2
where u2.categoria = a.categoria and year(u2.fecha) = 2007) as ingreso2007
from parapersonales a
Bastará que ahora tengas un único DataSource para tus dos DBGrid's, y que en uno de los DBGrid uses las columnas de los campos de un año, y en el otro DBGrid las columnas de los campos del otro año. Cuando te muevas en uno de los Grid, automáticamente el otro también se moverá a la posición correspondiente del otro año por estar apuntando al mismo DataSource
