Ir al contenido


Foto

[RESUELTO] Insertar todas las fechas dentro de un Rango de fechas


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

#1 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 13 marzo 2010 - 07:44

Pues eso, estoy tratando de insertar en una tabla todas las fechas dentro de un rango de fechas, o sea, en un rango desde 07/03/2010 hasta el 10/03/2010 quisiera insertar las fechas:

07/03/2010
08/03/2010
09/03/2010
10/03/2010

Tengo lo siguiente:



delphi
  1. procedure TFAstGen.btn1Click(Sender: TObject);
  2. var FechaIni, FechaFin: TDateTime;
  3. begin
  4. FechaIni := Primero;
  5. FechaFin := Ultimo;
  6.  
  7. QGetRows.Close;
  8. QGetRows.SQL.Clear;
  9. QGetRows.SQL.Text := 'SELECT * FROM LOG_ASISTENCIA';
  10. QGetRows.Open;
  11.  
  12. //pbProgreso.Max := QGetRows.RecordCount;
  13.  
  14. if QGetRows.RecordCount > 0 then begin
  15.   DateSeparator := '/';
  16.   ShortDateFormat := 'dd/mm/yyyy';
  17.   //Primero registramos todos los días x empleados
  18.   for FechaIni to FechaFin do begin
  19.     QGetLogData.Close;
  20.     QGetLogData.SQL.Clear;
  21.     QGetLogData.SQL.Text := 'INSERT INTO ASISTENCIA(EMP_ID,AST_FECHA) VALUES(:EMP, :FECHA)';
  22.     QGetLogData.ParamByName('EMP').Value := QGetRows.fieldByName('EMP_ID').AsInteger;
  23.     QGetLogData.ParamByName('FECHA').Value := FechaIni;
  24.     QGetLogData.ExecSQL;
  25.     QGetRows.Next;
  26.   end;
  27. end else ShowMessage('No hay registro que generar!');
  28. end;



El erro me da en el loop for:

[Error] AstGen.pas(93): For loop control variable must have ordinal type


Aquí me dice que deber un valor Ordinal (Entero), ahora cómo recorro fecha x fecha?


  • 0

#2 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 13 marzo 2010 - 07:53

Exacto Fernando.
No puede hacerse ese tipo de For con fechas, al menos no en las versiones anteriores a 2005... si en 2005 se añadió el for in, quizá exista algo como esto.

Lo que puedes hacer es:
1. Obtener la cantidad de días entre ambas fechas (DaysBetewn... mi inglés por dios)
2. Hacer un for desde 1 hasta la cantidad de días.
3. Disponer de una variable fechaini de tipo DateTime.

El truco para incrementar el día está en que en cada iteración, se sumes un día a la fechaini: AddDay()

Creo que esas pistas ya te haces una idea ;)

Saludos,
  • 0

#3 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 13 marzo 2010 - 07:56

Ah vale gracias Delphius, fíjate, ahora se me ocurrió si se puede listar una lista de fechas entre dos a través de una consulta, o sea, no de una tabla específica, sino a RDB$DATABASE, ¿es posible? porque así me sería más fácil pues.
  • 0

#4 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 13 marzo 2010 - 08:10

Ah vale gracias Delphius, fíjate, ahora se me ocurrió si se puede listar una lista de fechas entre dos a través de una consulta, o sea, no de una tabla específica, sino a RDB$DATABASE, ¿es posible? porque así me sería más fácil pues.

Déjame ver si entiendo... me desperté hace una hora :D y me faltó un poco de sueño |-) Todavía mi cerebro está cargandose... lleva un 50%

¿Quieres saber si es posible extraer un conjunto de fechas dado un rango pero desde una consulta SQL? Es decir tu quieres algo:

Fecha1 -> Primera
Fecha2
...
FechaN -> Última


Si es el caso, no creo que se pueda hacer mediante la tabla RDB$DATABASE porque ésta solo regresa un registro y tu buscas un conjunto.

Se que Firebird ya cuenta con varias funciones para fechas pero en estos momentos no te puedo asegurar si tiene algunas del tipo DaysBetween(), AddDay() como las que tiene Delphi. Seguramente sí, tendría que fijarme en la documentación de Firebird.

Pero eso sólo muy seguramente sea la mitad del paso... Deberás declarar un procedimiento almacenado para que puedas hacer algo como:

select from FechasEntre(FechaIni, FechaFin).

Este procedimiento FechasEntre() podría armarte el conjunto de datos con las fechas.

No se si esto te resultará más lioso que hacerlo por Delphi.

Saludos,
  • 0

#5 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 13 marzo 2010 - 08:22

Hola, me acabo de topar con un procedimiento almacenado cuyo aportador es de Chile y hace exactamente lo que necesito, lo probé y me guarda todos los días:



sql
  1. CREATE OR ALTER PROCEDURE DIAS_ENTRE_FECHAS (
  2.     FIRST$date DATE,
  3.     LAST$date DATE)
  4. RETURNS (
  5.     DAY$number INTEGER,
  6.     DAY$name CHAR(10),
  7.     DAY$date DATE)
  8. AS
  9. DECLARE variable DAY$week INTEGER;
  10. BEGIN
  11.   /* Procedure Text */
  12.  
  13.     DAY$date= FIRST$DATE;
  14.     DAY$number = 0;
  15.  
  16.     while (DAY$date <= LAST$DATE) DO
  17.     BEGIN
  18.           DAY$week=EXTRACT(weekday FROM DAY$date);
  19.  
  20.           IF (DAY$week=0) THEN
  21.             DAY$name='DOMINGO';
  22.           ELSE IF (DAY$week=1) THEN
  23.             DAY$name='LUNES';
  24.           ELSE IF (DAY$week=2) THEN
  25.             DAY$name='MARTES';
  26.           ELSE IF (DAY$week=3) THEN
  27.             DAY$name='MIERCOLES';
  28.           ELSE IF (DAY$week=4) THEN
  29.             DAY$name='JUEVES';
  30.           ELSE IF (DAY$week=5) THEN
  31.             DAY$name='VIERNES';
  32.           ELSE IF (DAY$week=6) THEN
  33.             DAY$name='SABADO';
  34.  
  35.           DAY$number    = DAY$number+1;
  36.           suspend;
  37.  
  38.           DAY$date = DAY$date+1;
  39.     END
  40.  
  41.  
  42. END^



En lo que la cosa me ha quedado así:



delphi
  1. procedure TFAstGen.btn1Click(Sender: TObject);
  2. begin
  3. QGetRows.Close;
  4. QGetRows.SQL.Clear;
  5. QGetRows.SQL.Text := 'SELECT * FROM LOG_ASISTENCIA';
  6. QGetRows.Open;
  7.  
  8. //pbProgreso.Max := QGetRows.RecordCount;
  9.  
  10. if QGetRows.RecordCount > 0 then begin
  11.  
  12.   DateSeparator := '.';
  13.   ShortDateFormat := 'dd/mm/yyyy';
  14.   //Primero registramos todos los días x empleados
  15.   QGetDates.Close;
  16.   QGetDates.SQL.Clear;
  17.   QGetDates.SQL.Text := 'SELECT * FROM DIAS_ENTRE_FECHAS(:INICIO, :FIN)';
  18.   QGetDates.ParamByName('INICIO').Value := Primero;
  19.   QGetDates.ParamByName('FIN').Value := Ultimo;
  20.   QGetDates.Open;
  21.   while not QGetDates.Eof do begin
  22.     QGetLogData.Close;
  23.     QGetLogData.SQL.Clear;
  24.     QGetLogData.SQL.Text := 'INSERT INTO ASISTENCIA(EMP_ID, AST_FECHA) VALUES(:EMP, :FECHA)';
  25.     QGetLogData.ParamByName('EMP').Value := QGetRows.FieldByName('EMP_ID').AsInteger;
  26.     QGetLogData.ParamByName('FECHA').Value := QGetDates.Fields[2].Value;
  27.     QGetLogData.ExecSQL;
  28.     QGetDates.Next;
  29.   end;
  30.   DM.ZData.Commit;
  31. end else ShowMessage('No hay registro que generar!');
  32. end;


  • 0

#6 pcicom

pcicom

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 267 mensajes
  • LocationMéxico

Escrito 13 marzo 2010 - 08:27

Espero te sirva esto..



delphi
  1. procedure TFAstGen.btn1Click(Sender: TObject);
  2. Var  cSql:String;
  3. begin
  4.   cDesde := '03/07/2010':
  5.   cHasta := '03/10/2010';
  6.  
  7.   cSql := 'INSERT INTO ASISTENCIA (EMP_ID,AST_FECHA)  ';
  8.   cSql := cSql + '  SELECT EMP_ID, LOG_FECHA FROM LOG_ASISTENCIA ';
  9.   cSql := cSql + '  WHERE LOG_FECHA BETWEEN '+QuotedStr(cDesde)+' AND '+QuotedStr(cHasta);
  10.   Try   
  11.     qryTemp.SQL.Clear;   
  12.     qryTemp.SQL.Add(cSql);   
  13.     qryTemp.ExecSql;
  14.   except   
  15.     ShowMessage('No hay registro que generar!');
  16.   end;
  17. end;


  • 0

#7 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 13 marzo 2010 - 08:30

Me alegro de que ya exista algo hecho, ya me estaba poniendo a ver en la documentación.

Quizá la alternativa de pcicom también funcione.

EDITO:
Pues si, en efecto... le estamos complicando amigo :s. No hay método más directo y fácil amigo que el hacer un INSERT INTO... SELECT() teniendo como filtro un BETWEEEN :D.

Saludos,
  • 0

#8 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 13 marzo 2010 - 08:45

Así es, pero el caso es que se está haciendo referencia a una tabla y es lo que no quiero :D, gracias de todos modos. (y).
  • 0

#9 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 13 marzo 2010 - 08:52

Así es, pero el caso es que se está haciendo referencia a una tabla y es lo que no quiero :D, gracias de todos modos. (y).

Memoria.... 65%... :(

Pues no comprendo :s. ¿Sin referencia? ¿A qué te refieres?
Que campos y datos guardas en LOG_ASISTENCIA?

Saludos,
  • 0

#10 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 13 marzo 2010 - 08:58

Me refiero amigo Delphius que lo único que tendré como referencia son la primera y última fecha que se obtienen en otra consulta, y que en la consulta de las fechas no le hago select a una tabla, tal como lo hago con el procedimiento.
  • 0

#11 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 13 marzo 2010 - 09:51

Probando la opción de pcicom, funciona bien, pero no me registra los días que no están en la tabla LOG_ASISTENCIA, que es lo que me interesa, que se registren lo que están y los que no, por ejemplo:

LOG_ASISTENCIA:

[table]
[tr]
[td]EMP_ID[/td]
[td]LOG_FECHA[/td]
[/tr]
[tr]
[td]1[/td]
[td]07/03/2010[/td]
[/tr]
[tr]
[td]2[/td]
[td]07/03/2010[/td]
[/tr]
[tr]
[td]1[/td]
[td]08/03/2010[/td]
[/tr]
[tr]
[td]1[/td]
[td]09/03/2010[/td]
[/tr]
[tr]
[td]2[/td]
[td]09/03/2010[/td]
[/tr]
[/table]

Como verán el empleado 2 faltó el día 08/03/2010, con la consulta de pcicom sólo pasa los registros existentes :(.
  • 0

#12 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 13 marzo 2010 - 10:07

Disculpa mi tardanza, estaba comiendo.

Ahora entiendo mejor. Entonces no te queda otra que generar las fechas con un procedimiento.

Saludos,
  • 0

#13 Rolphy Reyes

Rolphy Reyes

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.092 mensajes
  • LocationRepública Dominicana

Escrito 13 marzo 2010 - 10:13

Saludos.

Enecumene, una vez tuve que realizar algo parecido, la solución por la que opte fue de siempre insertar la fecha calendario por ejemplo el mes completo.

Para realizar esto tienes la opción de hacerlo desde Delphi con sus funciones IncDay más unas que otras validaciones con sus respectivas inserciones.  Con Firebird puedes usar la nueva función DATEDIFF (FB 2.1) para saber los días de diferencia y ligarlo con un While e incrementar una variable para ir comparando y así por el estilo.

Es idea que se puede fácilmente plasmar y creo que es la que más te conviene porque estas manejando la asistencia del personal.
  • 0

#14 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.446 mensajes
  • LocationMéxico

Escrito 13 marzo 2010 - 10:38

Hola



delphi
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   i: integer;
  4.   FechaIni,FechaFin: Tdatetime;
  5.   Fecha: string;
  6. begin
  7.   ShortDateFormat := 'dd/mm/yyyy';
  8.   fechaIni := strtodate('07/03/2010');
  9.   fechaFin := strtodate('10/03/2010');
  10.   for i := trunc(fechaIni) to trunc(FechaFin) do
  11.   begin
  12.     Fecha := datetostr(i);
  13.     Memo1.lines.Add(fecha)
  14.   end;
  15. end;



Salud OS
  • 0

#15 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 13 marzo 2010 - 11:01

Wow, eso sí que era sencillo :$
  • 0

#16 enecumene

enecumene

    Webmaster

  • Administrador
  • 7.419 mensajes
  • LocationRepública Dominicana

Escrito 13 marzo 2010 - 11:40

Bueno al final me decidí por la de Egostar, ya todo quedó bien (y).
  • 0

#17 pcicom

pcicom

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 267 mensajes
  • LocationMéxico

Escrito 13 marzo 2010 - 03:56

Punto para EGOSTAR  :cheesy:
pcicom 0  :cry:
delphius 0  :cry:
rolphy reyes 0  :cry:


JEJEJEJE.-..
  • 1

#18 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.446 mensajes
  • LocationMéxico

Escrito 13 marzo 2010 - 08:42

Punto para EGOSTAR  :cheesy:
pcicom 0  :cry:
delphius 0  :cry:
rolphy reyes 0  :cry:

JEJEJEJE.-..


Nada nada, No me odien por ser guapo :p :D :D :D

Salud OS
  • 0

#19 Rolphy Reyes

Rolphy Reyes

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.092 mensajes
  • LocationRepública Dominicana

Escrito 13 marzo 2010 - 09:24

Punto para EGOSTAR  :cheesy:
pcicom 0  :cry:
delphius 0  :cry:
rolphy reyes 0  :cry:


JEJEJEJE.-..


Saludos.

Un punto plus para mi, porque la solución de Egostar es la misma solución que yo decía, lo que sucede es que Egostar la presento con sentencias distintas a la que yo promovía, pero al final Enecumene necesita el calendario completo.

Necesita decir cuando un empleado no asistió y para decir eso necesita indicar la fecha, que al final es cargar la fecha calendario. (y)
  • 1

#20 egostar

egostar

    missing my father, I love my mother.

  • Administrador
  • 14.446 mensajes
  • LocationMéxico

Escrito 13 marzo 2010 - 09:30

Asi es amigo Rolphy, lo que yo le propuese a Fernando era que se agregaran todas las fechas calendario y después solo actualizar las fechas que el empleado si asistio a laborar, mi lógica me dijo que es más fácil actualizar las fechas que si se asistieron a ir buscando que días no se presentó a laborar el empleado.


Salud OS
  • 0




IP.Board spam blocked by CleanTalk.