crystal-reports - tamaño - parametros crystal report sap
¿Hay alguna manera de hacer que Crystal Reports incluya una constante en una condición de unión, sin usar un objeto de comando SQL? (8)
Lo que quiero hacer es una combinación externa a una tabla, donde excluyo registros de la tabla unida en base a la coincidencia de una constante, sin embargo guardo los registros de la tabla principal. Por ejemplo:
SELECT a.id, a.other, b.baz
FROM a
LEFT OUTER JOIN b
ON a.id = b.id
AND b.bar = ''foo''
Resultados previstos:
id other baz -- ---------- ------- 1 Has foo Include 2 Has none (null) 3 Has foobar (null)
No puedo obtener los mismos resultados poniéndolo en la condición de filtro. Si uso lo siguiente:
SELECT a.id, a.other, b.baz
FROM a
LEFT OUTER JOIN b
ON a.id = b.id
WHERE (b.bar IS NULL OR b.bar = ''foo'')
Obtengo estos resultados incorrectos:
id other baz -- -------- ------- 1 Has foo Include 2 Has none (null)
Donde excluyó los registros de A que coinciden con un registro de B donde bar = ''foobar''. No quiero eso, quiero que A esté presente, pero B será nulo en ese caso.
La Tabla B tendrá múltiples registros que es necesario excluir, por lo que no creo que pueda filtrar esto por el lado de Crystal sin tener que lidiar mucho para evitar problemas con los registros duplicados de la tabla A.
No puedo usar un objeto de comando SQL, ya que la aplicación de terceros desde la que estamos ejecutando los informes parece ahogarse en los objetos de comando SQL.
No puedo usar vistas, ya que nuestro contrato de soporte no permite modificaciones en la base de datos, y nuestro proveedor considera agregar vistas a una modificación en la base de datos.
Estoy trabajando con Crystal Reports XI, específicamente la versión 11.0.0.895. En caso de que haga una diferencia, me estoy ejecutando contra una base de datos Progress 9.1E04 usando el controlador ODBC SQL-92.
Las tablas de muestra y los datos utilizados en los ejemplos se pueden crear con lo siguiente:
CREATE TABLE a (id INTEGER, other VARCHAR(32));
CREATE TABLE b (id INTEGER, bar VARCHAR(32), baz VARCHAR(32));
insert into A (id, other) values (''1'', ''Has foo'');
insert into A (id, other) values (''2'', ''Has none'');
insert into A (id, other) values (''3'', ''Has foobar'');
insert into B (id, bar, baz) values (''1'', ''foo'', ''Include'');
insert into B (id, bar, baz) values (''1'', ''foobar'', ''Exclude'');
insert into B (id, bar, baz) values (''1'', ''another'', ''Exclude'');
insert into B (id, bar, baz) values (''1'', ''More'', ''Exclude'');
insert into B (id, bar, baz) values (''3'', ''foobar'', ''Exclude'');
No estoy seguro de si puede hacer esto en Crystal, pero ¿qué le parece unirse a un Select?
SELECT a.id, x.baz
FROM a
LEFT OUTER JOIN
(SELECT id, baz FROM b WHERE bar = ''foo'') As x ON a.id = x.id
¿No puedes crear vistas apropiadas en la base de datos y basar tu informe en estas vistas? Estoy usando Crystal Reports en MSSQL y muchas veces solo creo vistas para evitar problemas similares.
Puedo ver dos soluciones:
a) acepte la presencia de filas múltiples (innecesarias) en B (y valores repetidos en A), calcule los totales usando runnign total de campos y / o fórmulas, no de manera fácil, pero casi siempre posible;
b) mueva B al subinforme (donde puede establecer filtros fácilmente) y comunique los valores necesarios entre el informe principal y el subinforme utilizando variables compartidas.
Los subinformes son una herramienta poderosa para resolver este tipo de problemas, a menos que sea necesario anidarlos (no es posible) o exportar informes a Excel (agrega líneas vacías, al menos en CR 9).
Añadiendo
(Isnull({b.bar}) OR {b.bar} = "foo")
a la fórmula de selección de registros debe actuar como espera.
** editar **
Un par de cosas más para probar:
- Use un controlador de base de datos diferente: el controlador nativo (que evita ODBC) puede actuar de manera diferente. Lo noté por primera vez con la sintaxis WITH: el controlador ODBC de SQL Server no funcionaba, pero el controlador nativo de SQL Server sí.
- Si bien sacrifica cierta flexibilidad, inserte la consulta en un Comando, suponiendo que pueda cumplir con el producto de terceros. Agregado para completar.
Los informes de Crystal no pueden generar esa declaración SQL de uso común en función de sus enlaces y los criterios de selección de informes. Tienes que usar un "comando" o construir una vista.
En resumen, Crystal apesta.
¿Es un procedimiento almacenado una opción para ti? De ser así, podría preseleccionar los conjuntos de datos de esa manera sin tener que recurrir a la opción de comando, y uno puede importar un procedimiento almacenado como lo haría con una tabla.
Propondría el procedimiento almacenado que select * from b where bar= ''foo''
y se une a eso, de modo que la tabla b se prefiltra, por lo que todo lo que tiene que hacer es unirse en el otro campo de unión.
Espero que ayude.
Me parece que no quiere aceptar las sugerencias de nadie, pero aquí hay una última oportunidad de todos modos. La solución que he usado recientemente, donde la base de datos debe permanecer intacta, es la siguiente:
- Configure el servidor de Tomcat para que pueda ejecutar algunas bondades de JSP e Hibernate.
- Grabar informes de Crystal para eclipse
- Generar informe en el diseñador de informes de cristal con datos falsos en una base de datos local conforme a cómo tendría los datos en un mundo ideal
- Usar java servlet pass List para cada uno de los alias de la tabla, de modo que el informe tenga los datos reemplazados directamente de los POJO. Por supuesto, los POJO pueden estar completamente compuestos en java al extraer el contenido de varias tablas de db y maquinarlas como mejor les parezca, lo que a menudo permite proporcionar un conjunto de datos completamente aplanados con los que Crystal informa que está muy feliz de trabajar.
No debe agregar condición de filtro para la tabla b por b.bar is null or b.bar = ''foo''
, pero tampoco debe acceder directamente a los atributos de la tabla b. Debería obtener todos los atributos por una condición if b.bar = ''foo''
través de una fórmula.