1

クエリから上位N行の結果セットを取得し、残りの行を1つの行にロールアップしようとしています。私は以下のようなクエリを思いつきました-私はこのシナリオを助け、このSQLにある多くの冗長性を排除することができる組み込みのOracleSQL関数を使用することについての提案を必要としています。

    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

これは、サブクエリのリファクタリングを説明するための教科書のケースのようです。

これが私の提案です:

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 に答える
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 に答える