1

我正在尝试从查询中获取包含前 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
 ) 

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

4

2 回答 2

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;
于 2011-05-24T18:46:36.943 回答
2

这似乎是说明子查询重构的教科书案例。

以下是我的建议:

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。

于 2011-05-24T17:52:11.067 回答