Pergunta

Eu gostaria de ter uma consulta simples em uma lista de membros que são indexados por um número e agrupá-los em 'cabazes' de igual tamanho. Assim, a consulta de base é:

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

Say I começar 1000 números de índice membro para trás, agora eu quero dividi-los em 10 grupos de tamanho igual por um índice de membro do máximo e mínimo. Algo como:

Membros ativos em 0 a 400: 100 Membros ativos em 401 através de 577: 100 ... Membros ativos em 1584 através de 1765: 100

O melhor que eu poderia vir acima com é repetidamente consultando para o max (my_members.member_index) com um limite rownum aumentando:

  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;
Foi útil?

Solução

NTILE é o caminho a percorrer -. Vale a pena ler-se em funções analíticas como eles podem extremamente simplificar o seu SQL

comentário pequeno no código original - fazendo uma restrição rownum antes um ORDER BY pode produzir 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;

ciclo final;

Tente o seguinte:

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 obter o resultado que você espera que você precisa fazer

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

(Nota - nos bastidores, a Oracle vai traduzir isso em uma espécie eficiente que só já detém os 'top 4 itens').

Outras dicas

É simples e muito mais rápido usando a função analítica NTILE:

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

documentação do Oracle 10g: "NTILE é uma função analítica Ele divide um conjunto de dados ordenados em uma série de baldes indicado por expr e atribui o número balde apropriado para cada linha Os baldes são numerados de 1 a expr..."

Obrigado pela ajuda. Demorou um tempo para trabalhar tudo isso em uma instrução (por certas razões, que também era um objetivo), então aqui está o que eu vim com que parece que funciona para mim:

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;

Dê-me meus 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

Dê uma olhada na instrução CASE no SQL e definir um campo de grupo baseado fora dos intervalos desejados.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top