我正在尝试从查询中获取前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
)
如果您对改进此查询有任何建议,请分享。
答案 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;