あなたの質問はまだやや曖昧であることに注意してください。Jの最大値を持つレコードが複数ある場合、何を返す必要がありますか。1つのレコードを返すのですか、それとも複数のレコードを返すのですか。私の答えは、1つのレコードを返したい場合にのみ当てはまります。
その場合、iのFIRST / LAST集計関数を使用した以下のクエリが、最も効率的なクエリです。
テーブルを使った小さなテスト:
SQL> create table testmax (i,j)
2 as
3 select 1, 2 from dual union all
4 select 2, 4 from dual union all
5 select 3, 3 from dual
6 /
Table created.
そして、LAST集計関数(http://download.oracle.com/docs/cd/B28359_01/server.111/b28286/functions076.htm#sthref1540)を使用したクエリ:
SQL> set autotrace on explain
SQL> select max(i) keep (dense_rank last order by j) i
2 , max(j)
3 from testmax
4 /
I MAX(J)
---------- ----------
2 4
1 row selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 44308443
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 26 | 3 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 26 | | |
| 2 | TABLE ACCESS FULL| TESTMAX | 3 | 78 | 3 (0)| 00:00:01 |
------------------------------------------------------------------------------
Note
-----
- dynamic sampling used for this statement (level=2)
また、1つのテーブルスキャンを使用しますが、すべての行で分析関数を使用します。この場合、単一の集計で問題なく動作します。
SQL> select i,j
2 from (
3 select i, j, max(j) over () max_j
4 from testmax
5 )
6 where j=max_j
7 /
I J
---------- ----------
2 4
1 row selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 1897951616
-------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3 | 117 | 3 (0)| 00:00:01 |
|* 1 | VIEW | | 3 | 117 | 3 (0)| 00:00:01 |
| 2 | WINDOW BUFFER | | 3 | 78 | 3 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL| TESTMAX | 3 | 78 | 3 (0)| 00:00:01 |
-------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("J"="MAX_J")
Note
-----
- dynamic sampling used for this statement (level=2)
これは、1つではなく2つのテーブルスキャンを使用します。
SQL> SELECT i, j
2 FROM testmax
3 WHERE j = ( SELECT MAX(j) from testmax )
4 /
I J
---------- ----------
2 4
1 row selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 3795151209
-------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 26 | 6 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL | TESTMAX | 1 | 26 | 3 (0)| 00:00:01 |
| 2 | SORT AGGREGATE | | 1 | 13 | | |
| 3 | TABLE ACCESS FULL| TESTMAX | 3 | 39 | 3 (0)| 00:00:01 |
-------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("J"= (SELECT MAX("J") FROM "TESTMAX" "TESTMAX"))
Note
-----
- dynamic sampling used for this statement (level=2)
よろしく、
ロブ。