--------------------------------------------------
From: "Oswaldo Hernández" <[EMAIL PROTECTED]>
Sent: Sunday, September 21, 2008 7:37 AM
To: "Alejandro D. Burne" <[EMAIL PROTECTED]>
Cc: "PostgreEs" <[email protected]>
Subject: Re: [pgsql-es-ayuda] Obtener los 3 valores mas altos por grupo de
una serie de registros
Alejandro D. Burne escribió:
Alguien tiene idea de como armar una consulta sql (si es que se puede)
para obtener los 3 valores máximos y agrupandolos por una determinada
columna, por ejemplo teniendo los siguientes datos:
Posible es, pero dudo mucho de la eficiencia con tablas grandes.
postgres=# CREATE TABLE pruebas.test3 (c1 integer NOT NULL, c2 integer NOT
NULL);
CREATE TABLE
postgres=# insert into pruebas.test3 values
postgres-# (1,1),(1,2),(1,3),(1,4),(1,5),
postgres-# (2,1),(2,2),(2,3),(2,4),(2,5),
postgres-# (3,1),(3,2),(3,3),(3,4),(3,5),(3,5),
postgres-# (4,1),(4,1),(4,5),(4,5),(4,5);
INSERT 0 21
postgres=# select t3.c1, t3.c2
postgres-# from pruebas.test3 t3
postgres-# where
postgres-# (select count(*) from
postgres(# (select * from pruebas.test3 g3 group by g3.c1, g3.c2)
w3
postgres(# where w3.c1 = t3.c1 and w3.c2 > t3.c2
postgres(# ) < 3
postgres-# group by t3.c1, t3.c2
postgres-# order by t3.c1, t3.c2 desc;
c1 | c2
----+----
1 | 5
1 | 4
1 | 3
2 | 5
2 | 4
2 | 3
3 | 5
3 | 4
3 | 3
4 | 5
4 | 1
(11 filas)
Alejandro, la solución que planteas funciona siempre y cuando NO EXISTAN
"c2" repetidos. Para probarlo llena la tabla con los siguientes datos:
insert into test3 values
(1,1),(1,2),(1,3),(1,4),(1,5), (1,5),
(2,1),(2,2),(2,3),(2,4),(2,5), (2,5),
(3,1),(3,2),(3,3),(3,4),(3,5),(3,5),
(4,1),(4,1),(4,5),(4,5),(4,5);
Nota que (1, 5) y (2, 5) estan repetidos. El select que planteas sigue dando
el mismo resultado, cuando el 5 debería aparecer dos veces para el "c1" 1 y
2.
"me acabo de dar cuenta que el (4,5) estaba repetido y no necesitaba
adicionar nuevas filas :-)"
Se me ocurre la siguiente solución, con índices por c1 y c2 debería reponder
aceptablemente:
select c1, max(c2) as c2
from test3
group by c1
union all
select c1, (select c2 from test3 where c1 = aux.c1 order by c2 desc limit 1
offset 1) as c2
from test3 aux
group by c1
union all
select c1, (select c2 from test3 where c1 = aux.c1 order by c2 desc limit 1
offset 2) as c2
from test3 aux
group by c1
RESULTADO:
4;5
2;5
3;5
1;5
4;5
2;5
3;5
1;5
4;5
2;4
3;4
1;4
Si quieres que salga ordenado puedes agregar la sentencia dentro de un
subquery en el from y hacer un order by, pero ten en cuenta que le aumentará
complejidad/tiempo a tu consulta y no siempre será necesario este
ordenamiento.
Atentamente,
RAUL DUQUE
Bogotá, Colombia
Saludos,
--
*****************************************
Oswaldo Hernández
oswaldo (@) soft-com (.) es
*****************************************
PD:
Antes de imprimir este mensaje, asegúrese de que es necesario.
El medio ambiente está en nuestra mano.
--
TIP 6: ¿Has buscado en los archivos de nuestra lista de correo?
http://archives.postgresql.org/pgsql-es-ayuda
__________ Information from ESET Smart Security, version of virus
signature database 3458 (20080921) __________
The message was checked by ESET Smart Security.
http://www.eset.com
--
TIP 2: puedes desuscribirte de todas las listas simultáneamente
(envía "unregister TuDirecciónDeCorreo" a [EMAIL PROTECTED])