1

番号でインデックス付けされたメンバーのリストに対して簡単なクエリを実行し、それらを同じサイズの「バケット」にグループ化したいと思います。したがって、基本クエリは次のとおりです。

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

1000 のメンバー インデックス番号が返されたとします。今度は、最大メンバー インデックスと最小メンバー インデックスによってそれらを 10 個の同じサイズのグループに分割したいと考えています。何かのようなもの:

0 ~ 400 のアクティブ メンバー: 100 401 ~ 577 のアクティブ メンバー: 100 ... 1584 ~ 1765 のアクティブ メンバー: 100

私が思いついた最善の方法は、rownum 制限を増やして max(my_members.member_index) を繰り返しクエリすることです。

  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;
4

4 に答える 4

2

NTILE 分析関数を使用すると、シンプルではるかに高速になります。

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

Oracle 10g ドキュメント: 「NTILE は分析関数です。順序付けられたデータ セットを expr で示されるバケット数に分割し、適切なバケット番号を各行に割り当てます。バケットには 1 から expr までの番号が付けられます。」

于 2009-05-08T05:39:51.330 に答える
1

助けてくれてありがとう。すべてを 1 つのステートメントにまとめるにはしばらく時間がかかりました (特定の理由でそれが目標でもありました)。

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;

次のような結果を教えてください。

member_index    ranger
2297683     1
2307055     2
2325667     3
2334819     4
2343982     5
2353325     6
2362247     7
6229146     8
8189767     9
26347329        10
于 2009-05-01T19:37:44.570 に答える
1

NTILE が最適です。SQL を大幅に簡素化できるため、分析関数について読む価値があります。

元のコードに関する小さなコメント - ORDER BY の前に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;

ループを終了します。

以下を試してください:

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;

期待する結果を得るには、あなたがする必要があります

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

(注 - 舞台裏で、Oracle はこれを「上位 4 項目」のみを保持する効率的なソートに変換します)。

于 2010-06-30T13:45:14.270 に答える
0

SQLのCASEステートメントを見て、必要な範囲に基づいてグループフィールドを設定します。

于 2009-05-01T18:47:05.973 に答える