FTP | CCD | Buscar | Trucos | Trabajo | Foros |
|
Registrarse | FAQ | Miembros | Calendario | Guía de estilo | Temas de Hoy |
|
Herramientas | Buscar en Tema | Desplegado |
#1
|
|||
|
|||
Filtrado de una tabla.
A ver si me podeis echar una mano porque en esto estoy más perdido que un pulpo en un garage.
Utilizo wxp y D5 y las tablas son Paradox. Os cuento, tengo dos tablas en mi aplicación. 1.- TablaClientes. 2.- TablaVisitas. En un formulario quiero que al seleccionar un cliente en un DBGrid me salgan las fechas de sus visitas (en otro dbgrid), hasta ahí bien, he hecho un maestro-detalle. Ahora lo que quiero es que al seleccionar una fecha de las que salen en el dbgrid me salgan los servicios realizados en esa fecha. Para ello puse un memo en el que volcaré los datos que encuentre para os servicios de esa fecha. El volcado no me supone problema, el problemasurge porque quiero filtrar por fecha del siguiente modo: Código PHP:
EdatabaseError with message 'Arithmetic in filter expresions not supported'. ¿Como puedo solucionar esto?. ¿Sería mejor que buscase otra solución?. Un saludo y gracias por vuestra atención.
__________________
- ¿Y cuando dejaré de aprender maestro?. - El día que te mueras pequeño saltamontes. |
#2
|
||||
|
||||
Bueno, en primer lugar yo te aconsejaria que trabajases o bien con consultas o vistas en lugar de con filtros, verás que mejoras el rendimiento y velocidad y disminuyes el tmp de respuesta del sistema.
Luego, creo que te falta mencionar que para los servicios tienes otra tabla ¿no?, la cual se encuentra relacionada en maestro:detalle con la tabla de visitas. Si no es así yo lo diseñaria de ese modo, ya que me parece mejor solución que no el volcarlo a un Memo. (es sólo mi opinión o consejo, vamos...) En cuanto al error, muy probablemente salte por la naturaleza de los datos en los que estas intentando realizar el filtro, es decir, el column.Field.AsString quizá es por el forzado de tipo String, mientras que el campo en el que estableces el filtro supongo que lo tendrás declarado como de tipo dateTime. Puede venir por ahí el error, creo yo. Suerte.
__________________
El meu país és tan petit, que des de dalt d'un campanar es pot veure el campanar veí. |
#3
|
|||
|
|||
Bueno, te habia respondido al otro hilo que tenias abierto y, luego me he dado cuenta que estaba este, asi que te pongo aqui lo que te habia contestado
Prueba algo asi Código:
var str : string; begin str := 'FechaVisita = ' + QuotedStr(FormatDateTime('mm/dd/yyyy', column.Field.AsDateTime)); modulodedatos.tablavisitas.filter := str; modulodedatos.tablavisitas.filtered := true; end; Bueno, espero te sirva PD: el formato de fecha dependera del motor de bases de datos que utilices (creo que en Paradox es eso, pero no recuerdo al 100%) EDIT: para evitar el scroll horizontal Última edición por __cadetill fecha: 25-07-2003 a las 15:53:30. |
#4
|
|||
|
|||
Hola a los dos:
Lo primero dar las gracias a Cadetil por cerrar el otro post (que era identico a este), creo que salió repetido porque le di al cabo del tiempo a refrescar la página. He hecho lo que me dijo Cadetil y funciona, pero no me he quedado muy satisfecho, ya que al hacer el filtro también me desaparecen las otras fechas de visita. La cuestión es que la tabla de visitas consiste en: - 1 campo indice_visitas - 1 campo clave_cliente - 1 campo fecha_visita - 7 campos servicio1, servicio2, servicio3, ... (no es probable que en una visita se hagan más de 7 servicios). En la tabla de servicios solamente he incluido: - 1 Campo Clave_servicio - 1 Campo Nombre_servicio - 1 Campo Precio_servicio Y luego tengo la tabla de clientes: Con la clave_cliente, nombre_cliente... Tal como lo tengo no puedo hacer un master:detail1:detail2. ¿Se os ocurre otra manera mejor de organizar las tablas? Lo de hacer una consulta lo he intentado, pero me he liado ¿sabeis de algún sitio donde expliquen bien lo de las consultas? Un saludo y gracias por vuestras respuestas. PD: Cadetil, el formato de fecha en Paradox era (dd/mm/yy).
__________________
- ¿Y cuando dejaré de aprender maestro?. - El día que te mueras pequeño saltamontes. |
#5
|
|||
|
|||
Debes crear un indice secundario para el campo fecha_visita en la tabla de visitas, usa el database desktop para ello,
Una vez que tengas el indice definido , supongamos que le has llamado , ifecha_visita, primero tienes que activarlo para la tabla: Tabla.IndexName:= 'ifecha_visita'; Lo que hara que los registros queden ordenador por el campo del indice (por fecha de visita). Despues si solo quieres mostrar los registros de esa fecha harias algo como: Tabla.SetRange( [ FechaInicial],[FechaFinal]); para Cancelar el rango: Tabla.CancelRange; para Desactivar el indice Table.IndexName:= ''; Pero parece que esta solucion no es la que te interesa, lo que quieres hacer es que se muestren todos los registros pero posicionarte en los de determinada fecha para ello haces algo como: Tabla.FindNeares([FechaABuscar]); La ventaja de usar indices, es que la operaciones sobre las tablas son infinitamente mas rapidas. Salud2 !! |
#6
|
|||
|
|||
Bien, tal y como lo veo, tenemos lo siguiente
Tabla Visitas --> Tabla Clientes con relacion N-->1 Esta relacion no hay problemas (segun comentas en tu primer post). Solo un comentario, el indice de la tabla visitas tendria que ser ID_Cliente ID_Visita Siempre ha de ir el indice de la tabla maestra al principio y luego el indice de la detalle. Ok, ya tenemos la relacion hecha. Para la siguienta tebla, Servicios, esta no es un detalle de Visitas. Tal y como yo lo veo (por lo que pones), ésta es un maestro de Servidios que nos informa de qué servicio es y el precio. Para hacer lo que quieres, es decir, coger la descripcion del servcio y el precio (creo entender que es eso), lo que yo haria es poner campos calculados en tu DataSet de Visitas que recuperaran la informacion que deseas de la tabla de Servicios Es eso lo que quieres? Ya nos contaras, espero te sirva |
#7
|
|||
|
|||
He hecho tal y como decía Cadetill:
TablaClientes --> TablaVisitas, y hasta ahí bien. Para acceder al servicio que se ha hecho al tener el código he hecho lo siguiente: Código:
Procedure RellenarDatosCliente; Var i : integer; indicedeservicios: array [1..7] of integer; Begin with FormularioPrincipal do Begin // recogida de indices de servicios indicedeservicios[1]:= modulodedatos.tablavisitasserviciorealizado1.value; indicedeservicios[2]:= modulodedatos.tablavisitasserviciorealizado2.value; indicedeservicios[3]:= modulodedatos.tablavisitasserviciorealizado3.value; indicedeservicios[4]:= modulodedatos.tablavisitasserviciorealizado4.value; indicedeservicios[5]:= modulodedatos.tablavisitasserviciorealizado5.value; indicedeservicios[6]:= modulodedatos.tablavisitasserviciorealizado6.value; indicedeservicios[7]:= modulodedatos.tablavisitasserviciorealizado7.value; // Localización en la tabla de servicios de esos índices e inserción del nombre en // el Memo1 for i := 1 to 7 do Begin with modulodedatos.tablaserviciosclaveservicio do Begin modulodedatos.TablaServicios.First; While not eof do if value = indicedeservicios[i] then memo1.lines[i] := modulodedatos.TablaServiciosnombreservicio.Value else Next; End; End; End; End;
__________________
- ¿Y cuando dejaré de aprender maestro?. - El día que te mueras pequeño saltamontes. |
#8
|
|||
|
|||
Cita:
Código:
modulodedatos.tablaserviciosclaveservicio.Eof De todas maneras, desde mi punto de vista, el codigo que has puesto no es muy eficiente. Podrias mirar de sustituirlo por algo asi (que quizas no da tantas vueltas a la tabla) Código:
var Q: TQuery; begin Q := TQuery.Create(Self); Q.DatabaseName := modulodedatos.TablaServicios.DatabaseName; Q.SQL.Text := 'select nombreservicio from TablaServicios where claveservicio = :valor'; try // primero Q.ParamByName('valor').Value := modulodedatos.tablavisitasserviciorealizado1.value; Q.Open; if not Q.Fields[0].IsNull then Memo1.Lines.Add(Q.Fields[0].AsString); // segundo Q.Close; Q.ParamByName('valor').Value := modulodedatos.tablavisitasserviciorealizado2.value; Q.Open; if not Q.Fields[0].IsNull then Memo1.Lines.Add(Q.Fields[0].AsString); // tercero Q.Close; Q.ParamByName('valor').Value := modulodedatos.tablavisitasserviciorealizado3.value; Q.Open; if not Q.Fields[0].IsNull then Memo1.Lines.Add(Q.Fields[0].AsString); // ........ finally FreeAndNil(Q); end; end; |
#9
|
|||
|
|||
Hola Cadetill.
He intentado las dos soluciones, vaya por delante que me parece más correcta la segunda. Pero ninguna la he podido llegar a concluir. En la primera me dice: [Error] UtilidadesAplicacion.pas(28): Undeclared identifier: 'eof' En el segundo caso (que es el que me gustaría implementar) no soy capaz de conseguir que me acepte el self: Me sale [Error] UtilidadesAplicacion.pas(52): Undeclared identifier: 'Self'.
__________________
- ¿Y cuando dejaré de aprender maestro?. - El día que te mueras pequeño saltamontes. |
#10
|
|||
|
|||
Veamos
Para la primera, mea culpa, hice un cortar y pegar y asi me feu Tendria que haber sido Código:
modulodedatos.tablaservicios.Eof La segunda opcion. No se donde estaras haciendo el Create (Form, DataModule,...), pero si no te acepta el Self, prueba Application (que esta definido en la unit Forms) Espero te sirva |
#11
|
|||
|
|||
Hola Cadetill:
Lo primero decirte que la primera opción funcionó perfectamente, con la modificación que me dijiste y alguna más, para solucionar una metedura de pata que tenía en el código que hacía que no terminara nunca el bucle con while. Con la segunda me pongo ahora a ver si doy con la solución, de momento he de decirte que es un procedimiento que tengo en una unidad, en ningún formulario. P.D. El código de la primera opción (la mala) quedaría así: Código:
Procedure RellenarDatosCliente; Var i : integer; indicedeservicios: array [1..7] of integer; Begin with FormularioPrincipal do Begin for i := 1 to 7 do memo1.Lines[i]:= ''; // recogida de indices de servicios indicedeservicios[1]:= modulodedatos.tablavisitasserviciorealizado1.value; indicedeservicios[2]:= modulodedatos.tablavisitasserviciorealizado2.value; indicedeservicios[3]:= modulodedatos.tablavisitasserviciorealizado3.value; indicedeservicios[4]:= modulodedatos.tablavisitasserviciorealizado4.value; indicedeservicios[5]:= modulodedatos.tablavisitasserviciorealizado5.value; indicedeservicios[6]:= modulodedatos.tablavisitasserviciorealizado6.value; indicedeservicios[7]:= modulodedatos.tablavisitasserviciorealizado7.value; // Localización en la tabla de servicios de esos índices e inserción del nombre en // el Memo1 for i := 1 to 7 do Begin with modulodedatos.tablaservicios do Begin modulodedatos.TablaServicios.First; While not eof do if modulodedatos.TablaServiciosClaveServicio.value = indicedeservicios[i] then Begin memo1.lines[i] := modulodedatos.TablaServiciosnombreservicio.Value; next; end else Next; End; End; For i := 1 to 7 do If memo1.Lines[i] = '0' then memo1.lines[i] := '' End; End;
__________________
- ¿Y cuando dejaré de aprender maestro?. - El día que te mueras pequeño saltamontes. |
#12
|
|||
|
|||
Cita:
Cita:
Código:
While not eof do begin if modulodedatos.TablaServiciosClaveServicio.value = indicedeservicios[i] then memo1.lines[i] := modulodedatos.TablaServiciosnombreservicio.Value; Next; End; |
#13
|
|||
|
|||
Tienes toda la razón nos ahorramos un par de líneas.
Con respecto a lo del application no he dado con ello. Probablemente porque no se la sintaxis que debo poner. He probado varias cosas con distintos resultados (pero todos negativos) . He probado a poner Q:= application.create(TQuery); y me dice: [Error] UtilidadesAplicacion.pas(56): Incompatible types: 'TComponent' and 'Class reference' También he probado: Q:= application.create(self); y me dice: [Error] UtilidadesAplicacion.pas(56): Undeclared identifier: 'self'
__________________
- ¿Y cuando dejaré de aprender maestro?. - El día que te mueras pequeño saltamontes. |
#14
|
|||
|
|||
cuando te decia que en lugar de Self utilizaras Application, me referia a algo asi
Q := TQuery.Create(Application); A ver ahora que tal |
#15
|
|||
|
|||
Hola de nuevo Cadetill:
He tardado en responder porque he "pescado" un gripazo que me ha tenido en cama 2 días. La solución que me propusiste funcionó a la perfección, solamente le añadí al principio del procedimiento una línea para borrar el memo1 antes de iniciar. Por si a alguien le puede servir dejo aquí el código final. Código:
Procedure RellenarDatosCliente; var Q: TQuery; begin with formularioprincipal do Begin memo1.Lines.clear; Q := TQuery.create(Application); Q.DatabaseName := modulodedatos.TablaServicios.DatabaseName; Q.SQL.Text := 'select nombreservicio from TablaServicios where claveservicio = :valor'; try // primero Q.ParamByName('valor').Value := modulodedatos.tablavisitasserviciorealizado1.value; Q.Open; if not Q.Fields[0].IsNull then Memo1.Lines.Add(Q.Fields[0].AsString); // segundo Q.Close; Q.ParamByName('valor').Value := modulodedatos.tablavisitasserviciorealizado2.value; Q.Open; if not Q.Fields[0].IsNull then Memo1.Lines.Add(Q.Fields[0].AsString); // tercero Q.Close; Q.ParamByName('valor').Value := modulodedatos.tablavisitasserviciorealizado3.value; Q.Open; if not Q.Fields[0].IsNull then Memo1.Lines.Add(Q.Fields[0].AsString); // ........ finally FreeAndNil(Q); end; End; end; Pues muchas gracias Cadetill, me has sido de gran ayuda.
__________________
- ¿Y cuando dejaré de aprender maestro?. - El día que te mueras pequeño saltamontes. |
|
|
|