Ordenación por cantidades en informe cruzado

0
9685

Ordenación por cantidades en informe cruzado

Introducción

Hace poco he estado trasteando con un informe de referencias cruzadas de JasperReports, usando iReport. El informe en cuestión nos cuenta quién hace qué y cuantas veces. Las columnas son las distintas acciones de la aplicación, las filas los distintos usuarios y en cada celda tendremos el número de veces que el usuario ha ejecutado la acción. El cliente, al ver el informe con datos reales, pidió que los usuarios que hiciesen «más cosas», apareciesen al principio del informe, un detalle bastante razonable si se está queriendo sacar alguna conclusión de toda esa actividad.

Ordenando por cantidades

Por lo visto no hay forma de decirle a iReport (o para el caso, a Jasper) que ordene teniendo en cuenta la cantidad. Ni siquiera parece haber forma de que ordene mediante cualquier otro criterio que no sea la columna de agrupamiento, por orden alfabético. En las propiedades del crosstab encontramos que se puede meter una expresión de ordenación. Pero el formato no está especificado ni documentado. Se supone que hay que pasar una clase que implemente java.util.Comparator (¿y cómo se le dice qué campos comparar con ella?). Pero no dan muchas esperanzas los mensajes de socorro sin contestar que salen en Google de quienes lo han intentado… y cayeron en el intento.

Afortunadamente para nosotros, existe una forma más fácil, que es especificar que queremos usar un dataset y que éste contendrá datos preclasificados. Esto se consigue marcando las dos casillas correspondientes en la pestaña de datos de las propiedades del crosstab. Si conseguimos una consulta que venga ordenada por actividad, está hecho.

La query existente venía a ser de la siguiente forma:

Como podéis ver, la consulta necesita restringir el resultado a trazas de aplicación, generadas por usuarios internos (que tenemos que cruzar con otra tabla) y limitando la fecha a un intervalo que nos pasan como parámetro. OK, nada de eso es relevante para el ejemplo, pero lo dejo para que se vea cómo se mueven las condiciones cuando la consulta se complique, que se complicará.

¿Habéis usado alguna vez la función count en SQL? Es la tentación natural, ¿y si pudiéramos meterla directamente en la consulta anterior? Algo así como:

No compila. Pero el mensaje de error de SQL Server da una buena pista.

No nos insulta por haber puesto el count, sino los otros campos. No pueden estar ahí, a no ser que formen parte del agregado… o de una cláusula GROUP BY. Así que metiendo los otros campos en un GROUP BY, podría funcionar. Pero el total que queremos es el de todas las acciones de un usuario, no un total por cada una de las acciones. Así que tendríamos que quitar el campo operation de la consulta y nos quedaría de esta forma:

Lo malo es que hemos perdido nuestro campo operation por el camino, no hay forma de meterlo si queremos resultados y que sean correctos. Además, necesitamos un registro por cada traza para que el crosstab lo contabilice, no una consulta de totales. Para resolverlo, unimos las dos consultas, haciéndolas subconsultas de una que las relaciona, así:

Vale, no es muy bonita la solución. Hemos tenido que añadir un nivel de anidamiento y repetir prácticamente la misma consulta, sólo para añadir un campo howmany, que ni siquiera vamos a ver, ya que sólo nos sirve para ordenar el resultado. Un alto precio por usar el count.

Por otra parte, es verdaderamente delicada: cualquier ligero cambio en de dónde sacamos los campos o cómo ordenamos y el informe deja de funcionar correctamente. Eso es porque el informe parece necesitar que le lleguen los datos en el orden en que va a agruparlos. Esta cuestión parece resolverla Jasper cuando es él quien controla los datos. Por dataset hace falta ser más cuidadoso y darle todo mascado.

 

Dejar respuesta

Please enter your comment!
Please enter your name here