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

我能想到的最好的办法是重复查询 max(my_members.member_index) 并增加 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;
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

谢谢您的帮助。花了一段时间才把它全部写成一个声明(出于某些原因,这也是一个目标),所以这就是我想出的看起来对我有用的东西:

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 回答