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)
-   -   ¿Cláusula similar al Break para procedimientos almacenados? (https://www.clubdelphi.com/foros/showthread.php?t=22117)

VRO 07-06-2005 12:43:38

¿Cláusula similar al Break para procedimientos almacenados?
 
Vereis tengo un procedimiento almacenado con Interbase 6.0 , lo que intento con él es sacar sólo 2 resultados de la consulta para cada campo clave, es decir,

Código:

1,....,0,0,...
 
5,....,2000,3000,....
5,...,2500,3500,....
.
.
10,....,2500,3500,....
10,....,2600,2000,....
.
.
15,....,2000,3000,...
15,....,1000,25000,....
.

para el numero 5 los 2 primeros resultados, para 10, para 15 y así sucesivamente con todos los números de contador que salgan en la consulta


él procedimiento de interbase es el siguiente:

Código:


cont=1;

FOR SELECT LECTURA
FROM LECTURAS
WHERE NUMERO=:NUMERO
AND FECHA<:HOY
ORDER BY FECHA DESC
INTO :LECT DO
BEGIN
  if (CONT=1) then
          lect1=:lect;
  else
          begin
                lect2=:lect;
          end
 
        cont=cont+1;
 
  if(cont>2) then
  begin
          suspend;
          break;
        end
END

os explico uun poquitín lo que hago, tengo una consulta a la que la paso un numero de contador(:numero) de una consulta anterior que no he especificado(lo que hace esta consulta es sacar los contadores que tengo con sus datos) y en esta saco las lecturas de esos contadores anteriores a la fecha actual. El cliente necesita saber las 2 leturas anteriores.

pero el break da error no es válido para interbase, con exit sólo me saca los 2 primeros del 5 y se sale del procedimiento, así que necesito algo similar al break.

Ahora lo que hago es sacar todas las lecturas anterioes y con el 'next' pasar de lecturas desde Delphi, pero tarda 14 segundos y me parece mucho tiempo.

Si alguien sabe la equivalencia de break en interbase u otra forma de hacer lo expuesto, se lo agradecería muchísimo.

Gracias de antemano.

PD: Espero haberme explicado con claridad, si alñguien no entiende lo expuesto ruego me lo comuniquen, ya saben uno lo tiene en la cabeza y le parece tan sencillo de explicar lo complicado es que le entiendan, jajajajaja

lbuelvas 08-06-2005 01:01:08

Chevere el ejercicio, me puse en la tarea de hacerlo, pero en Firebird 1.5.2, espero que
te sirva.

Meta usted unos valores, por aca en Colombia se le llaman contadores a los dispositivos
que cuentan el numero de metros cubicos que consume una casa y en algunos sistemas
para servicios publicos se considera el numero de contador como identificador unico.

En Colombia se le llama la 'critica' a la informacion de consumos de los 6 meses anteriores
para cualquier recibo de servicio publicos domiciliarios, y es de obligatorio cumplimiento
que esos valores aparezcan en el recibo.

El indice sugerido es mas rapido que uno basado en (fecha + contador).

El pedacito de codigo 'and :i < 3' es una ventaja de los procedimientos almacenados, es decir,
puede introducirse dentro del for select una condicion de salida que no tiene nada que ver con
los campos de la tabla seleccionada !!!

Haste unas pruebas de rendimiento con SQLHammer, es Open SOurce y cuenta con un analizador
de consultas (bueno realmente muestra las estadisticas de la consulta pero es muy bueno).

Código SQL [-]
CREATE TABLE LECTURA (
    ID_LECTURA INTEGER NOT NULL,
    CONTADOR INTEGER NOT NULL,
    FECHA DATE NOT NULL,
    VALOR INTEGER NOT NULL);

alter table LECTURA
add constraint PK_LECTURA
primary key (ID_LECTURA);

CREATE INDEX IDX_LECTURA_CONTADORFECHA
ON LECTURA (CONTADOR,FECHA);

SET TERM ^ ;

CREATE PROCEDURE SP_CRITICA (
    CONTADOR INTEGER,
    FECHA_REFERENCIA DATE)
RETURNS (
    VALOR_1 INTEGER,
    VALOR_2 INTEGER)
AS
DECLARE VARIABLE I INTEGER;
DECLARE VARIABLE VALOR_AUXILIAR INTEGER;
begin
  /* Este procedimiento saca los valore para la critica */

  /* Inicializar los valores en null por si hay menos de dos lecturas */
  valor_1 = 0;
  valor_2 = 0;

  /* Inicializar en 0 el contador */
  i = 0;
  for select valor
      from   lectura
      where  contador = :contador
      and    fecha <= :fecha_referencia
      and    :i < 3
      order  by fecha desc
      into   :valor_auxiliar
  do begin
    if       (i = 0) then
      valor_1 = valor_auxiliar;
    else if  (i = 1) then
      valor_2 = valor_auxiliar;
    i = i + 1;
  end

  suspend;
end
^

SET TERM ; ^

GRANT SELECT ON LECTURA TO PROCEDURE SP_CRITICA;

GRANT EXECUTE ON PROCEDURE SP_CRITICA TO SYSDBA;

jwmoreira 08-06-2005 02:31:05

Espero te sirva:
Código:

FOR SELECT FIRST 2 LECTURA FROM LECTURAS
          WHERE NUMERO=:NUMERO
          AND FECHA<:HOY
          ORDER BY FECHA DESC
          INTO :LECT
DO
BEGIN
        SUSPEND;
END

Saludos,
Jorge.

VRO 09-06-2005 10:44:18

Gracias a ambos por vuestra predisposición para ayudarme.

En primer lugar Jwmoreira no puedo utilizar el first 2 con interbase, lo probé pero esa cláusula es para Firebird, tambien lo intenté con limit 2 (que se utiliza en Visual Basic) y ha diferencia del first de situa al final de la consulta.

Para Ibuelvas, la forma de hallar el consumo de agua de una casa en Colombia y en España es exactamente la misma. Me has dejado alucina con lo de meter una variable cualquiera en una consulta para que me restringa el numero de veces que se ha de ejecutar.

Muchas gracias ha ambos me habeis servidor de mucha ayuda


La franja horaria es GMT +2. Ahora son las 22:35:50.

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