尝试获取前n行n行。虽然它给了我结果但是,它需要很多时间。我相信它扫描表两次。
Code used:
WITH TI AS
(SELECT * FROM
(SELECT
Column1,
Column2,
Colmn3
FROM TABLE
ORDER BY DESC
)
WHERE ROWNUM<=5),
T2 AS
(SELECT * FROM
(SELECT
Column1,
Column2,
Colmn3
FROM TABLE
ORDER BY ASC
)
WHERE ROWNUM<=5)
SELECT * FROM T1
UNION ALL
SELECT * FROM T2
我怎样才能更快地获取这个? 考虑到表格会定期更新。
答案 0 :(得分:2)
解决此问题的最佳方法部分取决于您的Oracle版本。这是一个非常简单(我怀疑,非常有效)的解决方案,使用版本12.1中添加的match_recognize
子句。
我使用标准EMPLOYEES
架构中的HR
表来说明它,按SALARY
排序。这里唯一的技巧是选择顶部和底部五行,并忽略它们之间的所有内容;那个(“忽略”)是{- ... -}
运算符在pattern
子句中的作用。
select employee_id, first_name, last_name, salary
from hr.employees
match_recognize(
order by salary desc
all rows per match
pattern ( a{5} {- a* -} a{5} )
define a as 0 = 0 -- For reasons known only to Oracle, DEFINE is required.
);
EMPLOYEE_ID FIRST_NAME LAST_NAME SALARY
----------- -------------------- ------------------------- ----------
100 Steven King 24000
101 Neena Kochhar 17000
102 Lex De Haan 17000
145 John Russell 14000
146 Karen Partners 13500
135 Ki Gee 2400
127 James Landry 2400
136 Hazel Philtanker 2200
128 Steven Markle 2200
132 TJ Olson 2100
答案 1 :(得分:1)
您可以使用analytic functions将单个查询和单个传递合并到表中,在这种情况下生成两个伪列:
select column1, column2, column3,
row_number() over (order by column1 desc) rn_desc,
row_number() over (order by column1 asc) rn_asc
from your_table;
然后使用该查询过滤为内联视图(或CTE):
select column1, column2, column3
from (
select column1, column2, column3,
row_number() over (order by column1 desc) as rn_desc,
row_number() over (order by column1 asc) as rn_asc
from your_table
)
where rn_desc <=5
or rn_asc <= 5;
我假设您的订单位于column1
,并选择your_table
作为表名,因为您没有包含该名称,因此请根据需要进行更改。根据您想要处理关系的方式,您可能希望使用rank()
或dense_rank()
函数。
从@ mathguy的评论来看,这可能表现得更好:
select column1, column2, column3
from (
select column1, column2, column3,
row_number() over (order by column1 desc) as rn,
count(*) over () as cnt
from your_table
)
where rn <=5
or cnt - rn < 5;