2011-05-24 58 views
1

我想從查詢中得到一個結果集的前N行,並有剩餘的行卷成一行。我想出了一個如下所示的查詢 - 我需要關於使用任何內置的oracle sql函數的建議,這些函數可以幫助解決這種情況,並消除我在這個sql中的大量冗餘。返回頂部N行,並有剩餘的行卷成一行 - oracle 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

這似乎是一個教科書案例來說明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'; 

在我的數據庫我想這對我其實有一個成本改善以及表 - 因人而異。

+0

我喜歡塊使用的。在這種情況下非常合適。一個小小的改進......你應該將你的聯盟切換到聯盟所有,因爲這兩套之間不會有重複。 – Craig 2011-05-24 18:47:59

+0

通常情況下,雖然在這種情況下總共只有10行, – DCookie 2011-05-24 18:50:13

+0

@Craig @DCookie非常感謝您的建議 - 以及關於相關查詢成本的詳細信息。 – user12002221 2011-05-24 19:15:56

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; 
+1

+1用於避免UNION。有趣的是,這種方式與原始查詢具有相同的總成本 - 我沒有看到成本的改善。 – DCookie 2011-05-24 19:07:51