2017-11-21 10 views
0

トップnボトムn行をフェッチしようとしています。それは私に結果をもたらしますが、それは多くの時間がかかります。私はそれがテーブルを2回スキャンすると信じています。トップ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

ご注文はどうですか?どのOracleのバージョン。結びつきがあれば何をしたいですか? (あなたが何を注文していても、6行をランダムに表示しますか?)サンプルデータ、動作中のクエリ、および予想される結果が参考になります。 –

+0

パフォーマンス質問には、 'EXPLAIN ANALYZE'と、テーブルサイズ、インデックス、現在の時間パフォーマンス、欲求時間などの情報が含まれている必要があります。'スロー 'は相対的な用語であり、比較のためには本当の値が必要です。 –

+0

'ORDER BY DESC'ですか? 'ORDER BY ASC'?どういう意味ですか? – mathguy

答えて

1

あなたはこの場合、2つの疑似生成、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; 
+0

ああ、私はオラクルが注文が同じであることを理解するのに十分スマートではないと信じています。一度にすべての行を読み込んでも、2回注文するので時間がかかります。 'row_number()'(1つの順序付けのみ)と 'count()'(順序付けなし)を使い、両方をWHERE節で使用する方がよいでしょう。 – mathguy

+0

@mathguyこれをcount()でどのように解決すればよいですか? –

+2

@JuanCarlosOropeza - WHERE句では、 'rn <= 5 or rn > = cnt - 5'を確認できます。 – mathguy

2

この問題を解決する最良の方法は、Oracleのバージョンに部分的に依存しています。ここでは、バージョン12.1で追加されたmatch_recognize節を使用した非常に単純な(そして、私は非常に効率的な)ソリューションです。

標準HRスキーマのEMPLOYEESテーブルを使用して、SALARYで注文します。ここでの唯一のトリックは、上部と下部の5行を選択し、その間のすべてを無視することです。 サブセクションでは、{- ... -}オペレータが実行するものです(「無視する」)。

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 
+0

私はパターンサブ句を知らなかった。私はそれを確かに試してみましょう。 –

関連する問題