2012-03-01 10 views
3

having句を使用すると、havingの前に評価されますが、返される行の数は後で評価されるようです。修正はおそらくサブクエリですが、それを避けることが可能ならば私はしたいと思います。私はを使用して、no_data_foundを避けています。返される行数と使用時の行数の差

この現象は、11.2.0.1.0、10.2.0.1.0、9.2.0.7.0で発生するので、明らかに意図されていますが、理由はわかりません。以下は簡単に複製可能な例です。

これはなぜ起こるのですか?私はcount(*)1を返すと予想していたでしょう。 documentationから

create table tmp_test1 as 
    select level as id, level as val 
    from dual 
connect by level <= 1000 
     ; 

Table created. 

create table tmp_test2 as 
    select level as id, level as val 
    from dual 
connect by level <= 1000 
     ; 

Table created. 

select count(*) as count 
    from tmp_test1 a 
    join tmp_test2 b 
    on a.id = b.id 
having max(a.val) = max(b.val) 
     ; 

    COUNT 
---------- 
     1000 

select 1 as num_rows 
    from tmp_test1 a 
    join tmp_test2 b 
    on a.id = b.id 
having max(a.val) = max(b.val) 
     ; 

    NUM_ROWS 
---------- 
     1 
+0

何が質問ですか?それは、(SQLを使用して)どのデータベースシステムにとっても完全に合理的かつ予期される動作です! – Mithrandir

+0

@Ben - あなたは何を返すと思いますか? –

+0

@ミスラディール、それとも?私は前にこれを見たことがない...私の質問はなぜですか?返される行の数は、having節が評価されていることを示していますが、なぜ前に評価されたのか分かりません。 – Ben

答えて

3

having句はグループレベルで動作 - いいえグループが指定されていない場合、これはデータセット全体を横切って動作していることを意味します。

これは(having条件が真の場合)having句なしgroup by句を任意のクエリでは、結果は0のみ行(having条件が偽である場合)、または1行を返すことができることを意味します。

+0

+1、それは何らかの論理を作ります... – Ben

3

GROUP BYはWHERE句のような振る舞いをしたので、使用されていません。

だから、それはこのようなものかもしれません:この部分はcount

having max(a.val) = max(b.val) 

のためにあなたの1000年を取得します

select count(*) as count 
    from tmp_test1 a 
    join tmp_test2 b 
    on a.id = b.id 

あなたに1つのレコードのみを取得します。


この場合、1つのレコードも取得されるためです。

select 1 as num_rows 
    from tmp_test1 a 
    join tmp_test2 b 
    on a.id = b.id 
having max(a.val) = max(b.val) 
     ; 
1

あなたはそれが間違っている考えている...

select count(*) as count 
    from tmp_test1 a 
    join tmp_test2 b 
    on a.id = b.id 

この部分は値1000年

having max(a.val) = max(b.val) 

で、1行のみを戻すだろうと、この部分はどこ条件として考えることができるものが適用されますあなたが以前に得たもの(一度だけ評価される)のために、そしてmax(a)= max(b)として、それは真を返します。

関連する問題