Pregunta

Me gustaría realizar una consulta simple en una lista de miembros indexados por un número y agruparlos en "grupos" de igual tamaño. Así que la consulta base es:

select my_members.member_index from my_members where my_members.active=1;

Digamos que recupero 1000 números de índice de miembros, ahora quiero dividirlos en 10 grupos de igual tamaño por un índice de miembros máximo y mínimo. Algo como:

Miembros activos de 0 a 400: 100  Miembros activos en 401 hasta 577: 100  ...  Miembros activos desde 1584 hasta 1765: 100

Lo mejor que pude encontrar es consultar repetidamente el max (my_members.member_index) con un límite de rownum creciente:

  for r in 1 .. 10 loop
  select max(my_members.member_index)
  into ranges(r)
  from my_members
   where  my_members.active = 1
   and rownum < top_row
   order by my_members.member_index asc;
   top_row    := top_row + 100;
  end loop;
¿Fue útil?

Solución

NTILE es el camino a seguir, vale la pena leer sobre las funciones analíticas, ya que pueden simplificar enormemente su SQL.

Pequeño comentario sobre el código original: hacer una restricción de rownum antes un ORDER BY puede producir resultados adversos

for r in 1 .. 10 loop
   select max(my_members.member_index)
   into ranges(r)
   from my_members
   where  my_members.active = 1
   and rownum < top_row
   order by my_members.member_index asc;
   top_row    := top_row + 100;

bucle final;

Prueba lo siguiente:

create table example_nums (numval number)

begin
    for i in 1..100 loop
        insert into example_nums values (i);
   end loop;
end;

SELECT numval FROM example_nums 
WHERE rownum < 5 
ORDER BY numval DESC;

Para obtener el resultado que espera hacer

SELECT numval FROM
   (SELECT numval FROM example_nums 
   ORDER BY numval DESC)
WHERE rownum < 5 

(Nota: detrás de escena, Oracle lo convertirá en una ordenación eficiente que solo contiene los '4 elementos principales').

Otros consejos

Es simple y mucho más rápido usando la función analítica NTILE:

SELECT member_index, NTILE(10) OVER (ORDER BY member_index) FROM my_members;

Documentación de Oracle 10g: " NTILE es una función analítica. Divide un conjunto de datos ordenados en un número de grupos indicados por expr y asigna el número de grupo apropiado a cada fila. Los cubos están numerados del 1 al expr. & Quot;

Gracias por la ayuda. Tomó un tiempo convertirlo todo en una declaración (por ciertas razones, eso también era un objetivo), así que esto es lo que se me ocurrió y parece que me funciona:

select max(member_index), ranger
  from (SELECT member_index,
                    CASE
                        WHEN rownum < sized THEN 1
                        WHEN rownum < sized*2 THEN 2
                        WHEN rownum < sized*3 THEN 3
                        WHEN rownum < sized*4 THEN 4
                        WHEN rownum < sized*5 THEN 5
                        WHEN rownum < sized*6 THEN 6
                        WHEN rownum < sized*7 THEN 7
                        WHEN rownum < sized*8 THEN 8
                        WHEN rownum < sized*9 THEN 9
                        ELSE 10
                     END ranger
             from my_members,
                    (select count(*) / 10 sized
                        from my_members
                      where active = 1)
            where active = 1
            order by member_index)
 group by ranger;

Dame mis resultados como este:

member_index    ranger
2297683     1
2307055     2
2325667     3
2334819     4
2343982     5
2353325     6
2362247     7
6229146     8
8189767     9
26347329        10

Eche un vistazo a la declaración CASE en SQL y configure un campo de grupo basado en los rangos que desee.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top