¿Cómo realizar un for-downto en Firebird?
Started by
enecumene
, Nov 26 2012 12:43 PM
13 replies to this topic
#1
Posted 26 November 2012 - 12:43 PM
Pues necesito realizar una consulta de los ültimos 12 meses a partir de la fecha actual, eso lo puedo hacer utilizando DATEADD(), pero necesito hacer una especie de recorrido "hacia atrás", como un for downto en delphi, pero en firebird creo se utiliza el while, pero no sé como entrarle, a ver si alguien me muestra un ejemplo sencillo sólo para entender su funcionamiento.
Saludos.
Saludos.
#2
Posted 26 November 2012 - 12:59 PM
Buscas algo así??
CREATE OR ALTER PROCEDURE NEW_PROCEDURE
returns (
d date)
as
declare variable i integer;
begin
i = 1;
while (i < 12) do
begin
d = dateadd(i * (-1) month to current_date);
i = i + 1;
suspend;
end
end
#3
Posted 26 November 2012 - 01:12 PM
Muchas gracias cadetill, ya iré a practicarlo.
Saludos.
Saludos.
#4
Posted 27 November 2012 - 09:59 AM
Hice lo siguiente utilizando consultas:
Me da error con la variable i en el where .
Saludos.
CREATE OR ALTER PROCEDURE LAST_TWELVES_STATS
returns (
mes integer,
totalmes numeric(15,2))
as
declare variable i integer;
BEGIN
I = 1;
while (I < 12) do
BEGIN
select sum(DESP_CANT), EXTRACT(MONTH FROM DESP_FECHA) from despachos
where EXTRACT(MONTH FROM DESP_FECHA) = EXTRACT(MONTH FROM dateadd(i * (-1) MONTH TO CURRENT_DATE)) INTO :totalmes, :mes;
i = i + 1;
suspend;
END
END
Me da error con la variable i en el where .
Saludos.
#5
Posted 27 November 2012 - 10:37 AM
Creo que el problema no es el "where" ni la "i", sino la sentencia SQL en sí. Tienes una función de agrupación (un Sum) pero no tienes ningún "group by" ;-)
Nos leemos
Nos leemos
#6
Posted 27 November 2012 - 11:01 AM
Gracias por responder Xavier, pero agregué el Group BY y aún así marca el error en el "i" del where:
Error:
Saludos.
BEGIN
I = 1;
while (I < 12) do
BEGIN
SELECT SUM(DESP_CANT), EXTRACT(MONTH FROM DESP_FECHA) FROM despachos
WHERE EXTRACT(MONTH FROM DESP_FECHA) = EXTRACT(MONTH FROM dateadd(i * (-1) MONTH TO CURRENT_DATE))
GROUP BY EXTRACT(MONTH FROM DESP_FECHA)
INTO :totalmes, :mes;
i = i + 1;
suspend;
END
END
Error:
delphi
Column does not belong to referenced table. Dynamic SQL Error. SQL error code = -206. Column unknown. I. At line 11, column 75.
Saludos.
#7
Posted 27 November 2012 - 11:15 AM
Al estar dentro de una sentencia SQL, el compilador interpreta la "i" como un campo de la tabla consultada. Para que lo interprete como una variable debes anteponerle ":"
Nos leemos
Nos leemos
#8
Posted 27 November 2012 - 11:26 AM
Muchas Gracias Xavier, ahora sí se ejecutó, lo malo es que no me suma los últimos 12 meses de este año sino de los 5 años de información que tengo
#9
Posted 27 November 2012 - 11:35 AM
Bueno, eso ya es cosa del filtro que le pones a la sentencia SQL. Si te fijas sólo comparas el mes. Deberías comparar también el año si sólo quieres un año jejejeje
Nos leemos
Nos leemos
#10
Posted 27 November 2012 - 12:14 PM
jejeje, dicen por ahí que 4 ojos ven mejor que 2 , ya me lanza los datos correctos, pero sí que tarda el asunto (de 10 a 20 segundos), el procedimiento quedó así:
¿Habrá una forma de agilizarlo?.
Saludos.
CREATE OR ALTER PROCEDURE LAST_TWELVES_STATS
returns (
mes integer,
totalmes numeric(15,2))
as
declare variable i integer;
BEGIN
I = 1;
while (I < 12) do
BEGIN
select sum(DESP_CANT), EXTRACT(MONTH FROM DESP_FECHA) from despachos
where EXTRACT(MONTH FROM DESP_FECHA) || EXTRACT(Year FROM DESP_FECHA) = EXTRACT(MONTH FROM dateadd(:i * (-1) MONTH TO CURRENT_DATE)) || EXTRACT(YEAR FROM dateadd(:i * (-1) MONTH TO CURRENT_DATE))
and DESP_ESTADO = 1 AND DESP_COMB = 2
GROUP BY Extract(month from desp_fecha) INTO :totalmes, :mes;
i = i + 1;
suspend;
END
END
¿Habrá una forma de agilizarlo?.
Saludos.
#11
Posted 27 November 2012 - 02:33 PM
Para acelerarlo, lo que tienes que hacer es definir un índice en la tabla "despachos" por los campos DESP_FECHA, DESP_ESTADO y DESP_COMB, algo como
No obstante tendremos un problema. Cuando se usa la función EXTRACT, ese campo no se tiene en cuenta en el momento de indexar. Así pues, lo que hay que hacer es sustituir la función EXTRACT por un between de fechas (entre el día 1 del mes y el último día del mes). Así pues, podríamos hacer algo así
Espero te sirva
CREATE INDEX NombreIndice
ON despachos (DESP_FECHA,DESP_ESTADO,DESP_COMB)
No obstante tendremos un problema. Cuando se usa la función EXTRACT, ese campo no se tiene en cuenta en el momento de indexar. Así pues, lo que hay que hacer es sustituir la función EXTRACT por un between de fechas (entre el día 1 del mes y el último día del mes). Así pues, podríamos hacer algo así
CREATE OR ALTER PROCEDURE LAST_TWELVES_STATS
returns (
mes integer,
totalmes numeric(15,2))
as
declare variable i integer;
declare variable m integer;
declare variable y integer;
declare variable fini date;
declare variable ffin date;
begin
i = 1;
while (i < 12) do
begin
/* la idea es acelerar la consulta. Para ello tenemos que definir un índice
por todos los campos que forman la WHERE. Dado que si se usa la función
EXTRACT ya no se contemplaría un índice establecido por el campo fecha,
tenemos que buscar el primer y último día del mes que queremos controlar
para así poder usar el BETWEEN.
Cómo no existe una función en PSQL que nos dé el último día del mes, lo
que haremos es posicionarnos en el mes+1, coger el día 1 de ese mes y
restarle 1 */
/* restamos los meses que toquen a current_date menos 1 para saber el mes que toca+1 */
fini = dateadd((i-1) * (-1) month to current_date);
/* sacamos mes y año de ese mes */
m = extract(month from fini);
y = extract(year from fini);
/* sacamos último día del mes que queremos => (1/mes+1/año)-1*/
ffin = cast(y || '-' || m || '-01' as date) - 1;
/* sacamos mes y año del mes correcto */
m = extract(month from ffin);
y = extract(year from ffin);
/* sacamos primer día del mes correcto */
fini = cast(y || '-' || m || '-01' as date);
/* inicializamos variables por si la sentencia SQL no devuelve valores */
totalmes = 0;
mes = 0;
/* lanzamos sentencia SQL */
SELECT SUM(DESP_CANT), EXTRACT(MONTH FROM DESP_FECHA)
FROM despachos
where
DESP_FECHA between :fini and :ffin and
DESP_ESTADO = 1 and DESP_COMB = 2
group by 2
into :totalmes, :mes;
i = i + 1;
suspend;
end
end
Espero te sirva
#12
Posted 28 November 2012 - 07:18 AM
¡wow!, ahora sí me lanza los datos casi instantaneo, ¡Muchíssimas gracias cadetill!! , doy pot resuelto el tema.
Saludos.
Saludos.
#14
Posted 28 November 2012 - 12:44 PM
Cierto Rolphy, esa fue mi primera opción, lo que pasa es que no vi cómo hacer la expresión para que me cogiera no sólo el extract, sino también los otros 2 campos necesarios para el índice ya que, como dice la documentación, o lo haces por columnas o por una expresión