2017-06-23 1 views
0

Ich habe folgende Datensatz:Partitioning durch% der Probe in PL SQL (Oracle)

Ranking Segment Month 
1 1 201501 
2 1 201501 
3 1 201501 
4 1 201501 
5 1 201501 
6 1 201501 
7 1 201501 
… 1 201501 
567 1 201501 
1 2 201501 
2 2 201501 
3 2 201501 
4 2 201501 
….. 2 201501 
456 2 201501 
1 1 201502 
2 1 201502 
3 1 201502 
4 1 201502 
5 1 201502 
6 1 201502 
7 1 201502 
… 1 201502 
326 1 201502 
1 2 201502 
2 2 201502 
3 2 201502 
4 2 201502 
… 2 201502 
562 2 201502 
........... 

Ich brauche jedes Segment in Gruppen aufgeteilt, die 5% davon enthalten. Da jedes Segment eine andere Anzahl von Verkäufen pro Monat hat, können Sie mir eine Idee geben, wie ich jedes Segment in 20 Gruppen aufteilen kann, die 5% davon enthalten, geordnet nach Rangfolge?

Vielen Dank!

Antwort

0

Eine Methode besteht darin, count(*) als eine Fensterfunktion zu verwenden. Es ist unklar, welche Art von Probe für jede Gruppe gewünscht wird.

Im Folgenden hat eine erste „n“ Probe unter der Annahme, dass ranking keine Lücken oder Duplikate haben:

select t.*, 
     floor(20 * (ranking - 1)/cnt) as grp 
from (select t.*, count(*) over (partition by segment, month) as cnt 
     from t 
    ) t; 

Wenn es Lücken oder Duplikate sind, können Sie row_number() verwenden, um eine korrekte Auszählung zu bekommen.

0

Sie sagen nicht, was Ihre erwartete Ausgabe ist, angesichts Ihrer Eingabedaten. Vielleicht ist ntile(), was Sie nach, z.B .:

WITH sample_data AS (SELECT LEVEL ranking, 1 SEGMENT, 201501 mnth FROM dual CONNECT BY LEVEL <= 21 UNION ALL 
        SELECT LEVEL ranking, 2 SEGMENT, 201501 mnth FROM dual CONNECT BY LEVEL <= 40 UNION ALL 
        SELECT LEVEL ranking, 1 SEGMENT, 201502 mnth FROM dual CONNECT BY LEVEL <= 60 UNION ALL 
        SELECT LEVEL ranking, 2 SEGMENT, 201502 mnth FROM dual CONNECT BY LEVEL <= 80) 
SELECT ranking, 
     segment, 
     mnth, 
     NTILE(20) OVER (PARTITION BY mnth, SEGMENT ORDER BY ranking) grp 
FROM sample_data; 

    RANKING SEGMENT  MNTH  GRP 
---------- ---------- ---------- ---------- 
     1   1  201501   1 
     2   1  201501   1 
     3   1  201501   2 
     4   1  201501   3 
     ... 
     19   1  201501   18 
     20   1  201501   19 
     21   1  201501   20 
     1   2  201501   1 
     2   2  201501   1 
     3   2  201501   2 
     4   2  201501   2 
     5   2  201501   3 
     ... 
     36   2  201501   18 
     37   2  201501   19 
     38   2  201501   19 
     39   2  201501   20 
     40   2  201501   20 
     1   1  201502   1 
     2   1  201502   1 
     3   1  201502   1 
     4   1  201502   2 
     5   1  201502   2 
     6   1  201502   2 
     7   1  201502   3 
     ... 
     54   1  201502   18 
     55   1  201502   19 
     56   1  201502   19 
     57   1  201502   19 
     58   1  201502   20 
     59   1  201502   20 
     60   1  201502   20 
     1   2  201502   1 
     2   2  201502   1 
     3   2  201502   1 
     4   2  201502   1 
     5   2  201502   2 
     6   2  201502   2 
     7   2  201502   2 
     8   2  201502   2 
     9   2  201502   3 
     ... 
     72   2  201502   18 
     73   2  201502   19 
     74   2  201502   19 
     75   2  201502   19 
     76   2  201502   19 
     77   2  201502   20 
     78   2  201502   20 
     79   2  201502   20 
     80   2  201502   20 

N. B. ntil füllt zuerst die früheren Buckets, z. Für Segment 1 und Monat 201501 in meinem obigen Beispiel hat grp = 1 2 Zeilen, während alle anderen 1 haben. Wenn du willst, dass es die späteren Buckets sind, die mehr gefüllt werden, kannst du einfach die Reihenfolge des Ntils umkehren und daß dann aus der Anzahl der Schaufeln + 1, so in Ihrem Fall subtrahiert, das wäre:

21 - NTILE(20) OVER (PARTITION BY mnth, SEGMENT ORDER BY ranking DESC) 
0

Sie sind für NTILE(20), die die Daten in Blöcken von 5% teilt jede suchen.

select ranking, segment, month 
from 
(
    select 
    ranking, segment, month, 
    ntile(20) over (partition by segment, month order by ranking) as tile 
    from mytable 
) 
where tile = 1 
order by month, segment, ranking;