Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Firebird e Interbase (https://www.clubdelphi.com/foros/forumdisplay.php?f=19)
-   -   Stored Procedure en Firebird complejo (https://www.clubdelphi.com/foros/showthread.php?t=74736)

gluglu 07-07-2011 17:00:50

Stored Procedure en Firebird complejo
 
Hola !

Estoy intentando crear un Stored Procedure en Firebird 2.1 de la siguiente manera :

1ª Consulta : De un conjunto de registros determinado que obtengo, los ordeno de una manera específica y sólo tomo el 1er registro.

Código SQL [-]
Select ....   order by .... rows 1

2ª y 3ª Consultas posterior : Hago un Select de registros determinados y me devuelve cada consulta un número de registros determinado

Estas tres consultas las tengo que unir y devolver los registros ordenados de manera ascendete por un campo Timestamp.

Hasta aquí más o menos no tengo problemas.

El problema que tengo ahora está en que entre cada uno de esos registros, ordenados por Timestamp (Fecha y Hora), necesito a su vez obtener un totalizado de registros que se han producido entre cada uno de los Timestamp's.

Me explico con un ejemplo y algunos datos : Supongamos que las tres primeras consultas me devuelven :
1 01.01.11 10:00
2 01.02.11 11:00
3 01.03.11 12:00
4 01.04.11 13:00
5 01.05.11 14:00

Mi consulta final debe devolverme además un totalizado de registros cuya fecha de creación haya sido entre los timestamp de 1 y 2, 2 y 3, 3 y 4 .... para que me quede al final algo así como

1 01.01.11 10:00
Totalizado = 5
2 01.02.11 11:00
Totalizado = 3
3 01.03.11 12:00
Totalizado = 0
4 01.04.11 13:00
Totalizado = 7
5 01.05.11 14:00

He intentado hacer un For Select con un Union entre las tres primeras consultas, para despues dentro del bucle begin end del 'For Select' realizar los cálculos de los totalizados, pero me encuentro con el problema de que la primera consulta incluye un 'order by' y un 'rows 1'. Ya que necesito que sólo me devuelva el primer registro de varios, es indispensable el 'order by' + 'rows 1'.

El problema es que después de un 'order by' y 'rows 1' no puedo ejecutar un 'Union'.

Código SQL [-]
For Select 1 ....
    order by ...
    rows 1
 
    union
    Select 2 ....
    union
    Select 3 ....
 
do begin
   Cálculo del Totalizado entre Fechas de Registros
end

Alguna idea o ayuda cómo enfocar este cálculo ?

Gracias ;)

guillotmarc 07-07-2011 17:10:56

Cita:

Empezado por gluglu (Mensaje 405745)
Hola !

Estoy intentando crear un Stored Procedure en Firebird 2.1 de la siguiente manera :

1ª Consulta : De un conjunto de registros determinado que obtengo, los ordeno de una manera específica y sólo tomo el 1er registro.

Código SQL [-]Select .... order by .... rows 1


2ª y 3ª Consultas posterior : Hago un Select de registros determinados y me devuelve cada consulta un número de registros determinado

Estas tres consultas las tengo que unir y devolver los registros ordenados de manera ascendete por un campo Timestamp.

Hasta aquí más o menos no tengo problemas.

El problema que tengo ahora está en que entre cada uno de esos registros, ordenados por Timestamp (Fecha y Hora), necesito a su vez obtener un totalizado de registros que se han producido entre cada uno de los Timestamp's.

Me explico con un ejemplo y algunos datos : Supongamos que las tres primeras consultas me devuelven :
1 01.01.11 10:00
2 01.02.11 11:00
3 01.03.11 12:00
4 01.04.11 13:00
5 01.05.11 14:00

Mi consulta final debe devolverme además un totalizado de registros cuya fecha de creación haya sido entre los timestamp de 1 y 2, 2 y 3, 3 y 4 .... para que me quede al final algo así como

1 01.01.11 10:00
Totalizado = 5
2 01.02.11 11:00
Totalizado = 3
3 01.03.11 12:00
Totalizado = 0
4 01.04.11 13:00
Totalizado = 7
5 01.05.11 14:00

He intentado hacer un For Select con un Union entre las tres primeras consultas, para despues dentro del bucle begin end del 'For Select' realizar los cálculos de los totalizados, pero me encuentro con el problema de que la primera consulta incluye un 'order by' y un 'rows 1'. Ya que necesito que sólo me devuelva el primer registro de varios, es indispensable el 'order by' + 'rows 1'.

El problema es que después de un 'order by' y 'rows 1' no puedo ejecutar un 'Union'.

Código SQL [-]For Select 1 .... order by ... rows 1 union Select 2 .... union Select 3 .... do begin Cálculo del Totalizado entre Fechas de Registros end


Alguna idea o ayuda cómo enfocar este cálculo ?

Gracias ;)

Hola.

Tienes una sintaxis alternativa al ROW 1, y es FIRST 1. En lugar de ir al final del comando SQL, va justo después del SELECT.

Lo he comprobado y no tiene ningún problema para ser usado en conjunción del UNION.

Código SQL [-]
For Select first 1 1 ....
      union     
      Select 2 ....     
      union     
      Select 3 ....   
do begin    
     Cálculo del Totalizado entre Fechas de Registros 
end

Casimiro Notevi 07-07-2011 17:11:47

No conocía el "rows 1", ¿funciona igual que el "select first 1 loquesea from latabla..." ?

gluglu 07-07-2011 17:15:22

:eek: :eek: :eek: ... que simple !!! ... y que tontería no saberlo !!!

... y yo ya me estaba creando un procedimiento almacenado nuevo que a su vez llamase a este !!

Gracias, voy a probarlo !! ;) ;) ;)

gluglu 07-07-2011 17:18:19

:mad: :mad: :mad: .... el First 1 sí que funciona bien, pero no puedo hacer el Union ya que la primera consulta está ordenada !!

Me dá error si hago el union con 'order by' en la primera consulta.

Casimiro Notevi 07-07-2011 17:45:41

Por decir algo: y si en lugar de poner "order by campotal, campocual, campopascual" pones "order by 1, 2, 3"

gluglu 07-07-2011 17:55:45

Gracias Casimiro, pero tampoco funciona ....

Está claro que normalmente el 'order by' de una unión de Select's, va al final del todo y ahí se han de utilizar números.

Pero por eso es lo que me lanza el error al intentar compilar el SP, y tener el primer Select con un order by. No tiene sentido para el compilador, aunque yo lo necesite así.

No tengo manera de hacerlo de otra manera. La primera consulta me devuelve varios registros y yo tengo que coger sólo el 1º de un orden determinado.

He optado, a espera de si alguien propone algo mejor, de hacer un nuevo SP que a su vez llame al otro, y ya hago todas las operaciones en el nuevo. De momento, aunque no he terminado, parece que así sí que funciona.

Gracias de nuevo a todos.

guillotmarc 07-07-2011 20:33:18

Cita:

Empezado por gluglu (Mensaje 405766)

.... el First 1 sí que funciona bien, pero no puedo hacer el Union ya que la primera consulta está ordenada !!

Me dá error si hago el union con 'order by' en la primera consulta.

Vaya, pues si que es un incordio.

Entonces puedes aplicar el SELECT FIRST 1 sobre una consulta ya ordenada. De esta forma el SELECT FIRST 1 no necesita estar ordenado.

Es decir :

Código SQL [-]
  SELECT FIRST 1 Campo1, Campo2
  FROM (SELECT Campo 1, Campo2 FROM Tabla1 ORDER BY Campo3)
UNION
  SELECT Campo4, Campo5
  FROM Tabla2
UNION
....

Saludos. :)

gluglu 07-07-2011 20:57:34

Pues tienes toda la razón ! ... no se me había ocurrido esa opción.

La verdad es que ya tengo lista el nuevo SP con la llamada al SP 'hijo', tal y como comenté antes. Así me funciona. Pero aun así, voy a ver lo que me indicás mas tarde, porque al final y al cabo es más claro tener todo en un único SP.

La verdad es que se me complicó bastante. Al final para realizar el cálculo intermedio, entre dos registros con sus Timestamp's correspondientes, he tenido que recurrir a declarar un Cursor en el SP y utilizar Variables Auxiliares.

Gracias de nuevo :p

PepeLolo 29-07-2011 00:39:59

Cita:

Empezado por gluglu (Mensaje 405788)
Pues tienes toda la razón ! ... no se me había ocurrido esa opción.

La verdad es que ya tengo lista el nuevo SP con la llamada al SP 'hijo', tal y como comenté antes. Así me funciona. Pero aun así, voy a ver lo que me indicás mas tarde, porque al final y al cabo es más claro tener todo en un único SP.

La verdad es que se me complicó bastante. Al final para realizar el cálculo intermedio, entre dos registros con sus Timestamp's correspondientes, he tenido que recurrir a declarar un Cursor en el SP y utilizar Variables Auxiliares.

Gracias de nuevo :p

El proceso es el correcto y te digo mas, has terminado por programar justo tal y como has planteado la pregunta.


La franja horaria es GMT +2. Ahora son las 19:24:30.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi