Ir al contenido


Foto

Filtrar Clientdataset por campo aggregate


  • Por favor identifícate para responder
8 respuestas en este tema

#1 Caminante21

Caminante21

    Member

  • Miembros
  • PipPip
  • 21 mensajes
  • LocationLima, Peru

Escrito 21 agosto 2014 - 06:22

Hola de nuevo aqui con una pequeña duda que espero me puedan ayudar a resolver.

Tengo un listado que muestra entre otras cosas los nombre de clientes y documentos que tiene pendientes. Hasta ahi todo bien pero a surgido la necesidad de filtrar los datos para mostrar los clientes con un numero determinado de documentos pendientes que sera especificado por el usuario del sistema. Los datos provieene de una consulta algo compleja y alimentan un clientdataset.
Asi que para obtener la cantidad de documentos por cliente use un campo aggregate con la expression Count(NombreCli) ahora solo faltaba filtrar los datos.
Intente algo asi:



delphi
  1. ClientDataSet1.Filtered:=false;
  2. ClientDataSet1.Filter:='CANTIDAD>=2'; //Por ejermplo
  3.   ClientDataSet1.Filtered:=true;




Pero me envio este error:

Field 'Cantidad' cannot be used in a filter expression.

Por lo que veo que no puedo usar un campo aggregate con la propiedad filter.

Asi que quisiera pedir me den alguna luz para lograr mi objetivo o alguna otra alternativa para hacerlo desde el clientdataset.

Gracias por la atencion


  • 0

#2 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 22 agosto 2014 - 09:04

El campo aggregate con la función COUNT no te sirve para lo que quieres lograr, puesto que este no te agrupa por Cliente, lo que hace es contar el número de registros que contenga la expresión que le pasas a la función.
Yo sugiero dos consultas, una maestra de estadísticas que traiga el número de documentos pendientes por cliente y otra de detalles que traiga los documentos pendientes por un cliente dado.
Si nos dices las estructuras de las tablas involucradas y el motor de la DB, con mucho gusto te ayudamos con las consultas y la mecánica.

Un cordial saludo.
  • 0

#3 cram

cram

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 832 mensajes
  • LocationMisiones, Argentina

Escrito 22 agosto 2014 - 11:31

Supongo que  el campo aggregate no puede ser usado en un filtro pues se contradicen sus usos. Uno requiere la totalidad de filas y el otro intenta seleccionarlas, todo en un mismo intento.
Podrías intentar hacer una selección, tal como esa que dices en la consulta compleja que alimenta el clientdataset y usar su salida como lista para otro slect que obtiene los datos restantes, así te liberas de los filtros, ya que además suelen ser ineficientes.

Saludos.
  • 0

#4 Caminante21

Caminante21

    Member

  • Miembros
  • PipPip
  • 21 mensajes
  • LocationLima, Peru

Escrito 22 agosto 2014 - 11:43

El campo aggregate con la función COUNT no te sirve para lo que quieres lograr, puesto que este no te agrupa por Cliente, lo que hace es contar el número de registros que contenga la expresión que le pasas a la función.


Hola gracia por la observacion pero en este caso lo uso con la propiedad groupinglevel y me muestra el numero agrupado correctamente...

Eso de tocar la consulta no se. Preferiria hacerlo en local. Pero ya he tomado nota de sus sugerencias.
  • 0

#5 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 22 agosto 2014 - 02:08

Preferiria hacerlo en local. Pero ya he tomado nota de sus sugerencias.


Entonces lo que puedes hacer es clonar el TClientDataset y entoces recorrer el clon par obtener el ID de los registros que cumplan con el criterio de cantidad que deseas, dichos Ids los puedes almacenar en una variable de tipo string, ya en ese punto haces el filtro sobre el TClientDataset original pero con base en los Ids obtenidos.

En seguida te  pongo un ejemplo de como hacerlo.

Saludos.
  • 0

#6 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 22 agosto 2014 - 02:21

Prueba con esto:



delphi
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   Clon: TClientDataSet;
  4.   s: string;
  5. begin
  6.   s := '';
  7.   Clon := TClientDataSet.Create(nil);
  8.   try
  9.     Clon.CloneCursor(OriginalDataset, false, false);
  10.     Clon.First;
  11.     while not Clon.Eof do
  12.     begin
  13.       if Clon.FieldByName('Cantidad').AsInteger >= 2 then
  14.         s := s + IntToStr(Clon.FieldByName('ID').AsInteger) + ',';
  15.       Clon.Next;
  16.     end;
  17.     if length(s) > 0 then
  18.       Delete(s, length(s) , 1); // Borramos la última coma
  19.  
  20.     OriginalDataset.Filtered := false;
  21.     OriginalDataset.Filter := 'ID IN ' + '(' + s + ')';
  22.     OriginalDataset.Filtered := true;
  23.   finally
  24.     Clon.Free;
  25.   end;
  26. end;



Saludos.

Edito para corregir error en en la parte  Delete del código.
  • 0

#7 Caminante21

Caminante21

    Member

  • Miembros
  • PipPip
  • 21 mensajes
  • LocationLima, Peru

Escrito 22 agosto 2014 - 03:25

Entonces lo que puedes hacer es clonar el TClientDataset y entoces recorrer el clon par obtener el ID de los registros que cumplan con el criterio...


Gracias por la sugerencia. no se me habia ocurrido pero al parecer un al clonar el dataset se pierden los campos agregados porque recibo el mensaje d que el campo no existe.
Gracias seguire probando..
  • 0

#8 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 22 agosto 2014 - 04:14

Si, al parecer TClientDataset no trata por igual a los aggregates, lo hace mediante el índice, prueba así:



delphi
  1. if Clon.Aggregates.Items[0].Value >= 2 then



o así:



delphi
  1. if varToStr( Clon.Aggregates.Items[0].Value) >= '2' then



Saludos.


  • 0

#9 Caminante21

Caminante21

    Member

  • Miembros
  • PipPip
  • 21 mensajes
  • LocationLima, Peru

Escrito 22 agosto 2014 - 04:56

Gracias por el dato lo probare.
Por el momento lo resolvi aplicando el conteo en el mismo clientdataset. Vere como puedo mejorarlo.
Gracias por la idea. Cada dia se aprende algo nuevo.
  • 0




IP.Board spam blocked by CleanTalk.