返回前N行并将剩余的行汇总到一行 - oracle sql

时间:2011-05-24 17:33:15

标签: sql oracle aggregate-functions summary

我正在尝试从查询中获取前N行的结果集,并将剩余的行汇总到一行中。我已经提出了如下的查询 - 我需要有关使用任何内置的oracle sql函数的建议,这些函数可以帮助解决这个问题,并消除了我在这个sql中的大量冗余。

    select label, count_id from 
(
select table1.NAME as label, count(table1.id) as count_id, 
      ROW_NUMBER() OVER (order by  count(table1.id) desc) AS rn  
      from table1 
      where table1.NAME like 'D%'
      group by table1.NAME
      )
      where rn <= 9  -- get top 9 rows
union

select 'Other' as label, sum(count_id) as count_id from 
(
select label, count_id from 
(
select table1.NAME as label, count(table1.id) as count_id, 
      ROW_NUMBER() OVER (order by  count(table1.id) desc) AS rn  
      from table1 
      where table1.NAME like 'D%'
      group by table1.NAME
      )
      where rn > 9 -- get rows after row-num 9
 ) 

如果您对改进此查询有任何建议,请分享。

2 个答案:

答案 0 :(得分:2)

这似乎是用于说明subquery refactoring的教科书案例。

以下是我的建议:

WITH q AS
(
SELECT table1.NAME AS label, COUNT(table1.id) AS count_id, 
      ROW_NUMBER() OVER (ORDER BY COUNT(table1.id) DESC) AS rn  
  FROM table1 
 WHERE table1.name LIKE 'D%'
 GROUP BY table1.name
)
SELECT label, count_id FROM q WHERE rn <= 9
UNION ALL
SELECT 'Other' AS label, SUM(count_id) AS count_id 
  FROM q
 WHERE rn > 9 
 GROUP BY 'Other';

在我的数据库中的表格上我尝试了这一点,我实际上也提高了成本 - YMMV。

答案 1 :(得分:2)

@ DCookie尝试回答的另一个变体:

WITH
q as ( 
    select
        table1.name as label,
        count(table1.id) as count_id,        
        row_number() over (order by count(table1.id) desc) as rn    
    from table1   
    where table1.name like 'D%'  
    group by table1.name
)
select
    case
        when rn <= 9
        then label
        else 'Other'
    end label,
    sum(count_id) count_id
from q
group by
    case
        when rn <= 9
        then label
        else 'Other'
    end;