2009-05-01 10 views
1

Ich möchte eine einfache Abfrage auf eine Liste von Elementen, die durch eine Nummer indiziert sind, und gruppieren sie in "Eimer" von gleicher Größe. So ist die Basisabfrage ist:SQL-Ergebnisse in Bereiche trennen

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

Sagen ich 1000 Mitglied Indexzahlen zurück, jetzt will ich sie in 10 gleich große Gruppen von max und min Mitglied Index aufzuspalten. Etwas wie:

Aktive Mitglieder in 0 bis 400: 100 Aktive Mitglieder in 401 bis 577: 100 ... Aktive Mitglieder in 1584 bis 1765: 100

Das Beste, was ich tun konnte wiederholt Abfragen für den max (my_members.member_index) mit einer zunehmenden rownum Grenze:

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; 

Antwort

1

NTILE ist der Weg zu gehen -.. Wert auf analytische Funktionen zu lesen, als sie enorm Ihre SQL vereinfachen

Kleine Kommentar auf dem Original-Code - tut eine rownum Einschränkung vor eine ORDER BY unerwünschten Ergebnissen führen kann

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; 

Endschleife;

Versuchen folgendes:

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; 

Um das gewünschte Ergebnis Sie erwarten

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

tun müssen (Hinweis - hinter den Kulissen wird Oracle diese in eine effiziente Art übersetzen, die immer nur die ‚Top 4 Artikel‘ hält).

0

an der CASE-Anweisung in SQL Werfen Sie einen Blick und ein Gruppenfeld setzt die Bereiche basierend off Sie wollen.

1

Danke für die Hilfe. Es dauerte eine Weile, es in einer Erklärung alle arbeiten (aus bestimmten Gründen, die auch ein Ziel war), also hier ist, was ich kam mit, dass sieht aus wie es funktioniert für mich:

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; 

Gib mir meine Ergebnisse wie folgt aus :

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

Gut gemacht. Du hast die 'NTILE' Funktion neu erfunden :) –

2

Es ist ganz einfach und viel schneller die NTILE analytische Funktion mit:

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

Oracle 10g Dokumentation. „NTILE eine analytische Funktion Es eine geordnete Daten aufteilt wird in eine Anzahl von Buckets gesetzt, die durch expr angezeigt werden, und weist jeder Zeile die entsprechende Bucket-Nummer zu. Die Eimer sind mit 1 bis expr nummeriert „