GeneXus Data Providers.

Me encantan los Data Providers, pero no los entiendo. Me gustan porque son muy potentes y escribiendo poco se puede lograr muchísimo, pero muchas veces no hacen lo que yo quiero, son bastante desobedientes.

Para poner un ejemplo, quiero hacer DP para mostrar Rankings de Ventas. Fue el ejemplo mas sencillo que se me ocurrió. 

Quiero mostrar el total de lo vendido:  
  • por Local
  • por Zona 
  • por Fecha. 

Los DP van a devolver un SDT Ranking que tenga el total vendido por las diferentes dimensiones

CASO 1: Ranking por Local 


Hice un Data Provider con la sintaxis: 

 y esto devuelve lo vendido por cada uno de los locales y todo muy sencillo. 

Hice un Webpanel, que permite seleccionar el Data Provider y muestra en SDT en una grilla y también pasa dicho SDT a XML para que sea fácil ver los datos crudos. 

Hasta acá, todo correcto y según lo esperado.

Ahora, quiero que me devuelva el SDT ordenado por lo la suma de lo vendido, pero aca empieza a complicarse. No encuentro la forma de salvar un el Data Provider, ni por la formula 

 ORDER SUM(Cantidad)  

ni por el elemento del SDT 

ORDER SUMCANTIDAD

Lo único que se me ocurre es ordenar el SDT luego que me lo devuelve el Data Provider, pero no logro hacerlo dentro del DP Esto es un problema si la cantidad de locales fuera muy grande y se quiere paginar, obligaría a recorrerlos todos y quedarme únicamente con los mayores, sufriendo bastante la performance. 

Cuando miro el SQL generado en el SDT

SELECT T1.[LocalId], T1.[LocalNombre], COALESCE( T2.[GXC1], 0) AS GXC1 FROM ([Locales] T1 WITH (NOLOCK) LEFT JOIN (SELECT SUM([Cantidad]) AS GXC1, [LocalId] FROM [Ventas] WITH (NOLOCK) GROUP BY [LocalId] ) T2 ON T2.[LocalId] = T1.[LocalId]) ORDER BY T1.[LocalNombre] 

alcanzaría cambiar el ORDER BY T1.LocalNombre por ORDER BY GXC1, por la limitación de ordenar por la formula, parece mas un problema de sintaxis del SDT que de dificultades en la generación. 


CASO 2: Total por Fecha

Ahora, me interesa sacar una lista ordenada por fecha de lo vendido,
La navegación, me muestra que va a hacer algo que no esta muy claro que es, pero no es lo que yo quiero.
Y genera el codigo SQL

SELECT DISTINCT T1.[VentaId], T1.[LocalId], T1.[Fecha], COALESCE( T2.[GXC1], 0) AS GXC1 FROM ([Ventas] T1 WITH (NOLOCK) LEFT JOIN (SELECT SUM([Cantidad]) AS GXC1, [VentaId], [LocalId] FROM [Ventas] WITH (NOLOCK) GROUP BY [VentaId], [LocalId] ) T2 ON T2.[VentaId] = T1.[VentaId] AND T2.[LocalId] = T1.[LocalId]) ORDER BY T1.[Fecha]

A pesar que en mi DP no aparece ni VentasId, ni LocalID en ningun lado, sin embargo el codigo generado lo agrega y el resultado que me da, es un SDT con un elemento por registro de la tabla de ventas, lo cual no es lo que yo quiero.  No me doy cuenta que es lo incorrecto.

CASO 3: Suma por Local, con Filtro.

Quiero un data provider, que me devuelva el total de lo vendido por local, pero con fecha mayor o igual a una dada.
Esto caso es igual que el CASO 1, que funcionaba correctamente pero le agrego un where por fecha
La navegación parece correcta, pero el resultado es:
El SQL que genera es:



Realmente, no la entiendo. .

Pruebo poniendo la condición en el SUM, de la forma:

y ahí si, el resultado es el esperado:

CASO 4: Total por Zona / Fecha 

Me gustaría poder tener un total por Zona y Fecha. 
El SQL que quiero emular es:

SELECT        Locales.ZonaId, Ventas.Fecha, SUM(Ventas.Cantidad) AS SumC
FROM            Ventas INNER JOIN
                         Locales ON Ventas.LocalId = Locales.LocalId
GROUP BY Locales.ZonaId, Ventas.Fecha

Hago el Data Provider. 
Y al ejecutar da un resultado incorrecto:



Supongo que debe existir una forma de expresar esta consulta, pero no la encontré.

CASO 5:  Total Zona / Fecha con Break

Intengo hacer un reporte de total por zona y por Fecha, usando el break, pero no lo logro. 
Hice el DP

el cual al correr dio el resultado (incorrecto)


pues no logro que el break lo haga por zona y fecha.

Resumiendo

Varias de las consultas que quiero hacer, no las puedo resolver, al menos en forma intuitiva.
Para resumir las dificultades fueron:

  • Ordenar por una formula 
  • Determinar los atributos que se usan para el Group By o Order By. 

Tal vez sea bueno revisar la sintaxis para hacer mas claras estas opciones.

Si alguien tiene la forma correcta de definir estos Data Provider, seria muy bueno que me lo hiciera saber, pues lo busque en la documentación y no pude encontrarlo.

Sugerencia / QuickTest. 

Para hacer mas fácil el desarrollo y la prueba de los Data Provider (y también de los Data Selector), me gustaría contar con una opción, que tome un DP y genere un webpanel que pida los parámetros del mismo como variables y me muestre el SDT resultado. Con eso, se haría mas rápida la adopción de los Data Providers, que son objetos muy poderosos pero poco comprendidos.

Si alguien le sirve para algo, les dejo el export de la KB que use para las pruebas con la TILO (72580).

UPDATE: Con posterioridad a la publicacion de este post, en  la GeneXus Tilo, se solucionan varios de los problemas que aca se plantean. Se agregó la sintaxis UNIQUE en los data providers, lo cual hace mas facil de entender los casos aqui planteados.




Recomiendo leer:



Comentarios

Entradas más populares de este blog

La nefasta influencia del golero de Cacho Bochinche en el fútbol uruguayo

Aplicación monolítica o distribuida?

Funcionalidades de GeneXus que vale la pena conocer: DATE Constants.