Question

Je voudrais poser une requête simple à une liste de membres indexés par un nombre et les regrouper en "compartiments" de taille égale. La requête de base est donc:

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

Disons que je récupère 1 000 numéros d’index membres. Je souhaite maintenant les séparer en 10 groupes de taille égale en fonction des index max et min. Quelque chose comme:

Membres actifs entre 0 et 400: 100  Membres actifs de 401 à 577: 100  ...  Membres actifs de 1584 à 1765: 100

Le mieux que je puisse trouver est d'interroger à plusieurs reprises le max (my_members.member_index) avec une limite de nombre croissant de Rownum:

  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;
Était-ce utile?

La solution

NTILE est la voie à suivre - il vaut la peine de lire les fonctions analytiques, car elles peuvent grandement simplifier votre SQL.

Petit commentaire sur le code d'origine - appliquer une restriction rownum avant avant que ORDER BY ne donne des résultats défavorables

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;

boucle de fin;

Essayez ce qui suit:

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;

Pour obtenir le résultat escompté, vous devez le faire

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

(Remarque: en coulisse, Oracle traduira ce résultat en un tri efficace ne contenant que les 4 éléments les plus consultés.)

Autres conseils

C’est simple et beaucoup plus rapide avec la fonction analytique NTILE:

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

Documentation Oracle 10g: "NTILE est une fonction analytique. Il divise un ensemble de données ordonné en un nombre de compartiments indiqué par expr et attribue le numéro de compartiment approprié à chaque ligne. Les compartiments sont numérotés de 1 à expr. "

Merci pour l'aide. Il a fallu un certain temps pour que tout soit intégré dans une seule déclaration (pour certaines raisons, c'était également un objectif), alors voici ce que j'ai proposé qui ressemble à cela fonctionne pour moi:

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;

Donnez-moi mes résultats comme ceci:

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

Examinez l'instruction CASE en SQL et définissez un champ de groupe basé sur les plages souhaitées.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top