选择最多n行A类的有限行数

时间:2015-11-30 00:39:13

标签: sql oracle oracle11g

是否可以在一个select语句中选择某些类型M(字符串或枚举字段)最多N行的有限量TM > N })? 到目前为止,我已经尝试使用DBMS_RANDOM这样,但它并不漂亮,并不能完全满足我的需求

select id from some_table 
         where ((type = 'A' and round(dbms_random.value(0,100)) > 75)
                or (type <> 'A'))
               and rownum < 1000;

编辑:
我正在处理的是一种使用数据库实现的队列。有K种不同类型的消息。 A类型的消息是低优先级的,它们每天一次或两次插入大约100k条记录。其他类型的消息具有更高的优先级并且不断插入。所以我试图实现的是以这样的方式处理这些记录:当插入类型A的消息时,其他类型的消息不会挨饿。

2 个答案:

答案 0 :(得分:0)

我想你可以使用rownumunion all,但这可能会变得复杂。我认为row_number()更适合这个目的:

select t.*
from (select id, row_number() over (partition by type order by dms_random.value()) as seqnum
      from t
     ) t
where (type = 'A' and seqnum <= 100) and
      rownum < 1000;

答案 1 :(得分:0)

随机排序不保证您获得N类型A记录和M类型非A类记录。为了保证这一点,你需要明确说明它,这意味着拆分查询以生成行号。

天真的版本会使用UNION ALL operator

select id
  from t
 where type = 'A'
   and rownum < N
 union all
select id
  from t
 where type <> 'A'
   and rownum < M

此方法的主要缺点是需要对表进行两次扫描。您可以使用sub-query factoring(CTE)解决此问题,但使用ROW_NUMBER()等分析查询可能更为简单。如果您对类型进行分区,则可以使用生成的行号来独立限制:

select id
  from ( select id
              , type
              , row_number() over (partition by case when type = 'A' then 'A'
                                                     else 'B'
                                                end) as rnum
           from t
                )
 where ( type = 'A' and rnum < N )
    or rnum < M