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)
-   -   Seleccionar primer y ultimo registro (https://www.clubdelphi.com/foros/showthread.php?t=59259)

Jose Roman 19-08-2008 15:26:38

Seleccionar primer y ultimo registro
 
Hola a todos, Tengo Firebird 2.0 y necesito realizar en un mismo SELECT el primer y ultimo registro. Gracias

roman 19-08-2008 16:07:57

Si se trata del primer y último registro respecto al orden de un campo o campos en particular, se me ocurre que podrías usar una unión:

Código SQL [-]
select first 1 columna, columna, ... from tabla order by campo

union

select first 1 columna, columna, ... from tabla order by campo desc

// Saludos

Jose Roman 19-08-2008 17:46:52

Gracias por la respuesta, tengo otra duda se que firebirs tiene LAST, en que parte se utiliza?

pcicom 19-08-2008 18:06:36

select [FIRST]/[LAST] <---- aqui en el ejemplo que te ponen aparece despues de SELECT

RolphyReyes 19-08-2008 18:27:46

Cita:

Empezado por pcicom (Mensaje 308353)
select [FIRST]/[LAST] <---- aqui en el ejemplo que te ponen aparece despues de SELECT

Cita:

Empezado por Jose Roman (Mensaje 308353)
Gracias por la respuesta, tengo otra duda se que firebirs tiene LAST, en que parte se utiliza?

Me es extraño, porque hasta donde tengo entendido la sentencia LAST como tal no existe sino NULLS LAST.

Código SQL [-]select a from gnull order by a asc nulls last;


La sentencia LAST la tiene los TDataSet en Delphi. Si estoy equivocado alguien que me corrija.

Hasta luego.

roman 19-08-2008 18:38:07

Cita:

Empezado por RolphyReyes (Mensaje 308358)
Si estoy equivocado alguien que me corrija.

No seré yo quien te corrija, pues, de hecho, yo ni siquiera conozco Firebird. Pero como sea que busqué "Firebird SELECT FIRST" en Google y encontré el comando, más no así (al menos a primera vista) con LAST, fue que puse el ordenamiento inverso para la segunda parte. :)

// Saludos

BlueSteel 19-08-2008 18:42:07

yo he utilizado el last, aunque se utiliza haciendo referencia a la tabla o query en cuestion

Código Delphi [-]
Tabla.Last;
Query.Last;

y lo que hace es poner el cursor en el último registro de la tabla o query seleccionado

Código Delphi [-]
Tabla.First;
Query.First;

y este pone el cursor en el primer registro...

Código Delphi [-]
Tabla.Next;
Query.Next;
y con esto avanzas un registro

Salu2:p:D

egostar 19-08-2008 18:49:14

Hola

Es que a raíz del título de la pregunta:

Seleccionar primer y ultimo registro

Lo que roman ha puesto es lo que se "tiene" que hacer, ni mas ni menos, mas claro ni el agua :)

No le busquemos tres pies al gato :D

Salud OS

roman 19-08-2008 18:54:12

Cita:

Empezado por egostar (Mensaje 308368)
Lo que roman ha puesto es lo que se "tiene" que hacer, ni mas ni menos, mas claro ni el agua :)

¿O sea que le atiné? :D

Pero entiendo la inquietud del LAST. Si existiera al igual que FIRST, podría hacerse la consulta así:

Código SQL [-]
select first 1 columna, columna, ... from tabla order by campo

union

select last 1 columna, columna, ... from tabla order by campo

sin necesidad de ordenar inversamente, lo cual quizá fuera más adecuado. Como diije, desconozco FB, pero creo haber leído que aún teniendo un índice sobre campo, el order BY DESC no es óptimo a menos que se haga un índice inverso sobre el mismo campo.

// Saludos

egostar 19-08-2008 19:06:58

Cita:

Empezado por roman (Mensaje 308370)
¿O sea que le atiné? :D

Pues parece que esto es mas complejo de lo que pensé, traté de hacer esto en una consulta en FB y me da error, no se puede usar UNION sobre la misma tabla :eek:


Código SQL [-]
select first 1 * from extensiones order by extension
union
select first 1 * from extensiones order by extension desc

Cita:

Invalid token.
Dynamic SQL Error.
SQL error code = -104.
Token unknown - line 2, char 1.
union.
Interesante, veamos como se resuelve, tal vez con un SP :)

Salud OS

roman 19-08-2008 20:00:51

Cita:

Token unknown - line 2, char 1.
Amigo Eliseo, quita el guión de tu consulta :D

Pero ya en serio, se me hacer extraño que no acepte esa unión. Buscando en los foros he visto, por ejemplo, esta pregunta, en la que se hace un union a la misma tabla y la queja no parece ir por ahí. :confused:

// Saludos

lbuelvas 19-08-2008 20:09:20

El problema que se te presenta egostar es que no puedes utilizar la clausula order by en uniones, el order lo puedes colocar al final de la union para indicar el orden del resultado final.

Lo mejor es utilizar un procedimiento almacenado, si alguien encuentra una forma mejor por favor nos dice.

Miremos el ejemplo:

Código SQL [-]
CREATE TABLE FACTURAS (
    ID_FACTURA   INTEGER NOT NULL,
    ID_CLIENTE   INTEGER NOT NULL,
    FECHA        DATE NOT NULL,
    VALOR_TOTAL  NUMERIC(15,2) NOT NULL
);


/* Primary Keys  */


ALTER TABLE FACTURAS ADD CONSTRAINT PK_FACTURAS PRIMARY KEY (ID_FACTURA);


/* Indices */

CREATE INDEX IDX_FACTURAS_FECHA ON FACTURAS (FECHA);

/* Datos */
INSERT INTO FACTURAS (ID_FACTURA, ID_CLIENTE, FECHA, VALOR_TOTAL) VALUES (1, 1, '2008-01-01', 50000);
INSERT INTO FACTURAS (ID_FACTURA, ID_CLIENTE, FECHA, VALOR_TOTAL) VALUES (2, 1, '2008-01-01', 100000);
INSERT INTO FACTURAS (ID_FACTURA, ID_CLIENTE, FECHA, VALOR_TOTAL) VALUES (3, 1, '2008-02-01', 20000);
INSERT INTO FACTURAS (ID_FACTURA, ID_CLIENTE, FECHA, VALOR_TOTAL) VALUES (4, 2, '2008-02-01', 40000);
INSERT INTO FACTURAS (ID_FACTURA, ID_CLIENTE, FECHA, VALOR_TOTAL) VALUES (5, 3, '2008-02-01', 80000);
INSERT INTO FACTURAS (ID_FACTURA, ID_CLIENTE, FECHA, VALOR_TOTAL) VALUES (6, 4, '2008-02-01', 90000);
INSERT INTO FACTURAS (ID_FACTURA, ID_CLIENTE, FECHA, VALOR_TOTAL) VALUES (7, 2, '2008-03-01', 120000);

Supongamos por ejemplo que queremos saber la primera y la ultima factura entre dos fechas, este procedimiento lo puede hacer:

Código SQL [-]
SET TERM ^ ;

CREATE OR ALTER PROCEDURE SP_FACTURAS (
    fecha_inicial date,
    fecha_final date)
returns (
    id_factura integer,
    fecha date,
    valor_total numeric(15,2))
as
begin
  -- Procedimiento para saber la primera y la ultima factura
  -- en un rango de fechas

  -- Busca la primera factura
  select first 1 id_factura,
                 fecha,
                 valor_total
  from  facturas
  where fecha between :fecha_inicial and :fecha_final
  order by id_factura
  into :id_factura,
       :fecha,
       :valor_total;
  if (id_factura is not null) then
    suspend;

  -- Busca la ultima factura
  select first 1 id_factura,
                 fecha,
                 valor_total
  from  facturas
  where fecha between :fecha_inicial and :fecha_final
  order by id_factura desc
  into :id_factura,
       :fecha,
       :valor_total;
  if (id_factura is not null) then
    suspend;
end^

SET TERM ; ^

GRANT SELECT ON FACTURAS TO PROCEDURE SP_FACTURAS;

GRANT EXECUTE ON PROCEDURE SP_FACTURAS TO SYSDBA;

El if (id_factura is not null) es para evitar que te salgan registros nulos cuando no hay facturas en el ranog de fechas.

Ejecuta el procedimiento con estos casos, correlos uno por uno

Código SQL [-]
select * from SP_FACTURAS('01/01/2008', '01/01/2008');
select * from SP_FACTURAS('01/01/2008', '01/04/2008');
select * from SP_FACTURAS('01/04/2008', '01/04/2008');

Espero que les sea de utilidad.

Jose Roman 19-08-2008 20:13:47

Ok, viendo todo lo anterior en definitava solamente se resuelve mediante un procedimiento almacenado, gracias a todos por ayudarme

roman 19-08-2008 20:33:32

Gracias Luis Fernando, ya se me ha aclarado que el problema está en el order by y de hecho, ya sabiendo eso, veo que es cosa del sql estandard que no permite eso en una unión.

Nuevamente, gracias.

// Saludos

lbuelvas 19-08-2008 20:35:46

Encantado de poderles servir.


La franja horaria es GMT +2. Ahora son las 07:41:04.

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