Re: [Sl-prog] Primera fila de un grupo en SQL

477 views
Skip to first unread message

Diego Mauricio Paz Carrillo

unread,
Jan 9, 2007, 10:19:24 PM1/9/07
to Camilo, sl-...@googlegroups.com
2007/1/10, Diego Mauricio Paz Carrillo <dim...@gmail.com>:
> SELECT ID_ESTACION,FECHA_REPORTE FROM `prueba` GROUP BY ID_ESTACION;
>
> Aunque me causa curiosidad para que lo necesitas, ya que el resultado
> puede cambiar si la tabla esta desordenada (a medida que se insertan y
> se eliminan campos), .... supongo que antes de realizar esto, la
> ordenas, no?
>
> 2007/1/10, Camilo <camilo...@gmail.com>:
> > Tengo esta tabla en la base de datos:
> >
> > ID_ESTACION FECHA_REPORTE
> > 1 01/01/1900 23:59:59
> > 1 01/01/1910 23:59:59
> > 1 01/01/1923 23:59:59
> > 1 01/01/1945 23:59:59
> > 2 01/01/1999 23:59:59
> > 2 01/01/1945 23:59:59
> > 2 01/01/1919 23:59:59
> >
> > y me gustaria obtener la primera fila de las que tienen el mismo
> > ID_ESTACION, asi:
> >
> > 1 01/01/1900 23:59:59
> > 2 01/01/1999 23:59:59
> >
> > He estado probando con distinct, group by y having, pero luego de toda
> > una tarde no he conseguido nada.
> >
> > Alguien sabe como hacerlo en sql?
> >
> > --
> > Red-Handed un programa de radio para informaticos
> > http://www.red-handed.com.ar
> >
> > _______________________________________________
> > Sl-prog mailing list
> > Sl-...@listas.el-directorio.org
> > http://listas.el-directorio.org/cgi-bin/mailman/listinfo/sl-prog
> >
>

Camilo

unread,
Jan 10, 2007, 6:15:54 PM1/10/07
to sl-...@googlegroups.com
La tabla es esta:
ID_ESTACION FECHA_REPORTE TEXTO_REPORTE
1 01/01/1900 23:59:59 algo
1 01/01/1910 23:59:59 como
1 01/01/1923 23:59:59 esto
1 01/01/1945 23:59:59 es
2 01/01/1999 23:59:59 lo
2 01/01/1945 23:59:59 que
2 01/01/1919 23:59:59 tiene

y me gustaria obtener la fila con la fecha_reporte mas reciente para
cada uno de los ID_ESTACION, asi:

ID_ESTACION FECHA_REPORTE TEXTO_REPORTE
1 01/01/1945 23:59:59 es
2 01/01/1999 23:59:59 lo

Óscar López

unread,
Jan 10, 2007, 9:31:48 PM1/10/07
to sl-prog
Se me ocurre esta consulta:

SELECT a.id_estacion, a.fecha_reporte, a.texto_reporte
FROM reporte a,
(SELECT id_estacion, MAX(fecha_reporte) AS fecha_reporte
FROM reporte
GROUP BY id_estacion) b
WHERE a.id_estacion = b.id_estacion AND a.fecha_reporte =
b.fecha_reporte;

Sin embargo, no la encuentro muy satisfactoria, tanto la consulta
anidada como la condición del WHERE hacen un full table scan al
momento de ejecutarse. Si la tabla va a ser pequeña no importa, pero
si va a ser grande esto va a ser un problema.

Supongamos que le añadimos una llave primaria a la tabla. ¿A alguien
se le ocurre una forma más eficiente de hacer esta consulta?.

Diego Mauricio Paz Carrillo

unread,
Jan 10, 2007, 10:32:18 PM1/10/07
to sl-...@googlegroups.com
Hola Oscar...
Me parece que es inevitable el realizar una doble funcion, ya que hay
que ordenar primero antes de agrupar.

Sin embargo, otra alternativa seria:

SELECT ID_ESTACION,FECHA_REPORTE,TEXTO FROM (SELECT * FROM prueba
ORDER BY FECHA_REPORTE DESC) as m GROUP BY ID_ESTACION

2007/1/11, Óscar López <oscar.and...@gmail.com>:

Óscar López

unread,
Jan 11, 2007, 11:49:24 AM1/11/07
to sl-prog
Diego, esa consulta no funciona :P . No todas las columnas del SELECT
están en el GROUP BY.

Siguiendo con la solución que propuse arriba; si no se nos ocurre una
mejor forma de escribir la consulta, como mínimo deberíamos crear un
índice sobre la tabla:

CREATE UNIQUE INDEX reporte_idx ON reporte(id_estacion, fecha_reporte)

Diego Mauricio Paz Carrillo

unread,
Jan 11, 2007, 4:25:17 PM1/11/07
to sl-...@googlegroups.com
No funciona? En que RDBMS estas tratando Oscar?. Yo intente en MySQL
y PGSQL y funciono :P. Por cierto, en PGSQL hay una particularidad
para este tipo de problemas y es utilizar "SELECT DISTINCT ON" con
"GROUP BY", pero igual, eso no es estandar.

Saludos

Diego

2007/1/12, Óscar López <oscar.and...@gmail.com>:

Óscar López

unread,
Jan 13, 2007, 12:22:32 AM1/13/07
to sl-prog
Y siguiendo con la saga de la "primera fila de un grupo" ...

Diego, estoy probando con PostgreSQL 7.4.5. Mi tabla es:

create table reporte (
id_estacion integer,
fecha_reporte date,
texto_reporte varchar(64)
);

insert into reporte values (1, '01/01/1900 23:59:59', 'algo');
insert into reporte values (1, '01/01/1910 23:59:59', 'como');
insert into reporte values (1, '01/01/1923 23:59:59', 'esto');
insert into reporte values (1, '01/01/1945 23:59:59', 'es');
insert into reporte values (2, '01/01/1999 23:59:59', 'lo');
insert into reporte values (2, '01/01/1945 23:59:59', 'que');

Y por consola obtengo:

SELECT ID_ESTACION,FECHA_REPORTE,TEXTO_REPORTE
FROM (SELECT * FROM reporte


ORDER BY FECHA_REPORTE DESC) as m

GROUP BY ID_ESTACION;

ERROR: column "m.fecha_reporte" must appear in the GROUP BY clause or
be used in an aggregate function

... Que no se me hace raro, no puedo poner en un SELECT una columna que
no este en el GROUP BY. Lo que me sorprende es que si te funcione!.

Saludos,

-Oscar.

Wilfredo I. Pachón López

unread,
Jan 17, 2007, 9:27:18 AM1/17/07
to sl-...@googlegroups.com
Óscar López <oscar.and...@gmail.com> escribió:
>create table reporte (
> id_estacion integer,
> fecha_reporte date,
> texto_reporte varchar(64)
>);

>insert into reporte values (1, '01/01/1900 23:59:59', 'algo');
>insert into reporte values (1, '01/01/1910 23:59:59', 'como');
>insert into reporte values (1, '01/01/1923 23:59:59', 'esto');
>insert into reporte values (1, '01/01/1945 23:59:59', 'es');
>insert into reporte values (2, '01/01/1999 23:59:59', 'lo');
>insert into reporte values (2, '01/01/1945 23:59:59', 'que');

En PostgreSQL utilizando la sentencia SQL:

SELECT DISTINCT ON (FECHA_REPORTE) FECHA_REPORTE, ID_ESTACION,TEXTO_REPORTE
FROM reporte ORDER BY FECHA_REPORTE DESC;

Utilizando los mismos datos de esta tabla de ejemplo, obtengo:
fecha_reporte id_estacion texto_reporte
1999-01-01 2 lo
1945-01-01 1 es
1923-01-01 1 esto
1910-01-01 1 como
1900-01-01 1 algo

El manual de PostgreSQL hace la siguiente observación respecto a la clausula
DISTINCT ON:

The DISTINCT ON expression(s) must match the leftmost ORDER BY
expression(s). The ORDER BY clause will normally contain additional
expression(s) that determine the desired precedence of rows within each
DISTINCT ON group.

Según veo creo que esto soluciona el problema.
--
Att:

Wilfredo I. Pachón López []
wilfr...@cun.edu.co
Coordinador de Tecnologías de Software
Gerente Proyecto SIIC -Sistema Integrado de Información CUN-
Dirección Nacional de Sistemas -CUN-
01/17/2007


Reply all
Reply to author
Forward
0 new messages