トップページに戻る    次のSQLパズルへ    前のSQLパズルへ

1-6 select文の評価順序

select文は、

 1. from句
 2. where句 (結合条件)
 3. start with句
 4. connect by句
 5. where句 (行のフィルタ条件)
 6. group by句
 7. having句
 8. model句
 9. select句
10. union、minus、intersectなどの集合演算
11. order by句

の順に評価されます。
(Oracle12c新機能のFetch First句とOffSet句は、order by句の後に評価されます)

分析関数を使う時や、
select文の文法エラーを修正する時や、
select文のチューニングを行う時に、
select文の評価順序を知っていると役に立つことがあります。

select文を読みときは、
select文の評価順序で読むようにし、

select文を書くときは、
脳内では、select文を読むときと同じ順序とし、
エディタで記述するときは、select句から順番、
とすれば効率がいいでしょう。

■■■補足1 RowNumの採番■■■
where句の条件を満たした順に、RowNumが振られる

SQL> select Val,max(rownum)
  2    from (select Val
  3            from (select 1 as Val from dual
  4        union all select 1 from dual
  5        union all select 1 from dual
  6        union all select 1 from dual
  7        union all select 2 from dual
  8        union all select 2 from dual
  9        union all select 2 from dual
 10        union all select 2 from dual
 11        union all select 3 from dual
 12        union all select 3 from dual
 13        union all select 3 from dual)
 14          order by dbms_random.random())
 15  where Val in (2,3)
 16  group by Val;

VAL  MAX(ROWNUM)
---  -----------
  2            6
  3            7

■■■補足2 distinctは分析関数の後■■■
SQL> select distinct Val,count(*) over(order by Val) as c
  2    from (select 1 as Val from dual
  3    union all select 1 from dual
  4    union all select 1 from dual
  5    union all select 1 from dual
  6    union all select 2 from dual
  7    union all select 2 from dual
  8    union all select 2 from dual
  9    union all select 2 from dual
 10    union all select 3 from dual
 11    union all select 3 from dual
 12    union all select 3 from dual);

VAL   C
---  --
  1   4
  2   8
  3  11

■■■補足3 distinctは分析関数の後、group byは分析関数の前■■■

SQL> select distinct ColA,ColB,Row_Number() over(order by 1) as Rn
  2  from (select 1 as ColA,1 as ColB from dual
  3  union all select 1,1 from dual
  4  union all select 1,1 from dual
  5  union all select 1,1 from dual
  6  union all select 2,2 from dual
  7  union all select 2,2 from dual
  8  union all select 2,2 from dual)
  9  order by 1,2,3;

ColA■ColB■Rn
----■----■--
   1■   1■ 1
   1■   1■ 2
   1■   1■ 3
   1■   1■ 4
   2■   2■ 5
   2■   2■ 6
   2■   2■ 7

7行が選択されました。

SQL> select ColA,ColB,Row_Number() over(order by 1) as Rn
  2  from (select 1 as ColA,1 as ColB from dual
  3  union all select 1,1 from dual
  4  union all select 1,1 from dual
  5  union all select 1,1 from dual
  6  union all select 2,2 from dual
  7  union all select 2,2 from dual
  8  union all select 2,2 from dual)
  9  group by ColA,ColB
 10  order by 1,2,3;

ColA■ColB■Rn
----■----■--
   1■   1■ 1
   2■   2■ 2

■■■補足4 階層問い合わせを使った場合■■■
マニュアル(英語)
マニュアル

Oracleは次のように階層問合せを処理します。
・最初に、結合(指定されている場合)が、FROM句で指定されているか、
  またはWHERE句述語で指定されているかが評価されます。
・CONNECT BY条件が評価されます。
・残りのWHERE句述語が評価されます。

階層問い合わせとwhere句は、
結合条件が階層問い合わせ前に評価され、
行のフィルタ条件は階層問い合わせ後に評価されるらしい・・・

where句に、結合条件と、行のフィルタ条件が混ざる場合は、
読みやすいだろうから、Join構文で結合させますが ;-)

with t as(
select 10 as Val from dual union all
select 11 as Val from dual union all
select 30 as Val from dual union all
select 31 as Val from dual union all
select 32 as Val from dual union all
select 33 as Val from dual)
select Val,max(Val)
  from t
Start With Val in(10,30)
connect by prior Val = Val-1
group by Val
order by Val;

Val  max(Val)
---  --------
 10        10
 11        11
 30        30
 31        31
 32        32
 33        33

with t as(
select 10 as Val from dual union all
select 11 as Val from dual union all
select 30 as Val from dual union all
select 31 as Val from dual union all
select 32 as Val from dual union all
select 33 as Val from dual)
select *
  from t
Start With Val in(10,30)
connect by prior Val = Val-1
group by Val
model
dimension by(val as soeji)
measures(max(Val) as mea)
rules()
order by soeji;

soeji  mea
-----  ---
   10   10
   11   11
   30   30
   31   31
   32   32
   33   33

create table keiro(ID,oya) as
select 1,null from dual union
select 2,   1 from dual union
select 3,   2 from dual union
select 4,   3 from dual;

select ID,Level
  from keiro,dual
 where ID = 2
Start With oya is null
connect by prior ID = oya;

ID  Level
--  -----
 2      2

select ID,Level
  from keiro join dual on (ID = 2)
Start With oya is null
connect by prior ID = oya;
レコードが選択されませんでした。

マニュアルによると、where句の記述はfrom句とStart With句の間のようです。

with t as(
select 10 as Val from dual union all
select 11 as Val from dual union all
select 30 as Val from dual union all
select 31 as Val from dual union all
select 32 as Val from dual union all
select 33 as Val from dual)
select Val
  from t
 where connect_by_IsLeaf=1
Start With Val in(10,30)
connect by prior Val = Val-1;

Val
---
 11
 33

■■■補足5 model句は、having句の後■■■
model句08 having句の次にmodel句が評価される

■■■補足6 PivotとUnPivot■■■
PivotもUnPivotも、from句の一部扱いと考えていいようです。
PivotやUnPivotした結果に表別名を付けれますので

select * from dual
unpivot(vals1 for key1 in(dummy,dummy,dummy,dummy,dummy))
unpivot(vals2 for key2 in(key1,key1))
pivot(max(key2) for vals2 in('DUMMY' as newDummy))
pivot(max(newDummy) for vals1 in('DUMMY' as newDummy2)) a
Join dual b
  on a.newDummy2 is null;

NEWDUMMY2  DUMMY
---------  ------
X          null

じょっぱりのぐだめぎ: select 文の評価順序
OTN-Japan 解説:GROUP BY だと NOT FOUND
OTN-Japan SELECT文