Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
DECODE関数とSIGN関数の魅力 - ORACLE小技箱
[go: Go Back, main page]

「IF」「THEN」「ELSE」というのは、プログラム言語には必須の制御のひとつですが、その機能を提供する関数が DECODE です。 ORACLEユーザの方は是非とも使いこなして頂きたい関数です。 これを使いこなせるようになると、大抵のことが一つのSQLで行えるようになることがおわかり頂けると思います。

使用例を示すと

SQL > SELECT NAME  "氏名" , SEX
  2 > , DECODE( SEX , 1 , '男' , '女' )  "性別" 
  3 > FROM PERSONAL ; 

氏名                  SEX  性別 
--------------------- ---- ---- 
徳川 家康            1    男 
与謝野 晶子          2    女 


この2行目の「DECODE( SEX , 1 , '男' , '女' ) 」の部分は、
     IF SEX = 1 THEN
        RETURN '男';
    ELSE
        RETURN '女';
    END IF;

という動きになってます。
これを、
     IF SEX = 1 THEN
        RETURN '男';
     ELSIF SEX = 2 THEN
        RETURN '女';
    ELSE
        RETURN '不明';
    END IF;

としたいのなら、「DECODE( SEX , 1 , '男' , 2, '女', '不明' ) 」とします。

※DECODEのパラメータは255まで指定可能です。

てな感じで、手軽にコードから名称への変換が行えるようになりますね。
ここまでは、ごく普通の使い方なのですが、DECODEの魅力(おもしろさ)はこれからです!

さて、このDECODEの動きを利用すれば、もっとすごいことができちゃうのですね。
その一つ、
DECODEを使用してカウントを取ることができます。
なーんだ!COUNT関数を使えばできるやん!と思ったあなた!!それは正しい。
でもDECODEはこんなカウントの取り方ができるのです。
SQL > SELECT SUM( DECODE( SEX , 1 , 1 , 0 ) )  "男性の人数" 
  2 > , SUM( DECODE( SEX , 2 , 1 , 0 ) )  "女性の人数" 
  3 > FROM PERSONAL ; 

男性の人数 女性の人数 
---------- --------- 
       198        172 

わかります?この理屈。順に追っていきましょう。

1. DECODE( SEX , 1 , 1 , 0 )
ここは、SEX の値が1の場合は、1 を返します。そうでなければ、0 を返します。まずこの動きを頭に置いといて!

2.SUM( ...)
ここは、1.で返してきた値をそれぞれ加算してます。
つまり、1つの行で、性別SEX が男性 1 の場合のみ、1が返ってきてますので、1が返ってきている件数を加算してやると、男性の人数が必然的に出てくる訳なんです。

3. DECODE( SEX , 2 , 1 , 0 )
こんどは、SEX の値が2の場合は、1 を返してます。
もうおわかりですね。あとは、2.と同様の理由で女性の人数が出てきますよね。
じゃー、COUNT関数を使用した場合とどう違うかって?
はい。COUNT関数だと以下のように2回SQLを発行しないといけないんです。
SQL > SELECT COUNT( SEX )  "男性の人数" 
  2 > FROM PERSONAL
  3 > WHERE SEX = 1 ;

SQL > SELECT COUNT( SEX )  "女性の人数" 
  2 > FROM PERSONAL
  3 > WHERE SEX = 2 ;

あるいは、この2つを結合して、
SQL > SELECT COUNT( A.SEX )  "男性の人数" 
  2 > , COUNT( B.SEX )  "女性の人数" 
  3 > FROM PERSONAL A , PERSONAL B ;
  4 > WHERE A.PERSONAL_ID = B.PERSONAL_ID
  5 >   AND A.SEX = 1 AND B.SEX = 2 ; 

(※ PERSONAL 主キーは、個人を特定するカラム PERSONAL_ID とします。)

あるいは、UNIONを使用したり...

おお〜、なんて面倒な〜。
いずれにしてもPERSONALテーブルを2回スキャンさせる必要があります。
DECODE関数だと1回のスキャンで済みます。


ここまでは、
IF A = B THEN 
    ... 
ELSEIF A = C THEN 
    ... 
ELSE 
    ... 
END IF; 

みたいな動きでしたよね。
ここまでくると、こういうこと(↓)できるといいなとおもいませんか?
IF A > B THEN 
    return 'Aの方が大きい' 
ELSEIF A < B THEN 
    return 'Bの方が大きい' 
ELSE 
    return '同じ大きさ' 
END IF; 

この動きのDECODE関数ともう一つ別のある関数を使用すればできてしまうんです。
そのある関数とは、SIGN 関数です。

関数SIGNの機能を確認していきましょう。
SQL > SELECT SIGN( 12 ) , SIGN( 0 ) , SIGN( -2 ) 
  2 > FROM DUAL ; 

SIGN( 12 )  SIGN( 0 )  SIGN( -2 ) 
-------------------------- 
         1          0          -1

このようにSIGN関数は数値をパラメータとして受け取ります。
そして下記のように、受け取った数値がプラスかマイナスかによって特定の値を返します。

+ => 1
- => -1
0 => 0
このSIGN関数の性質を知れば、「IF A > B THEN」の判定を行えそうですね。
結局...
SQL > SELECT DECODE( SIGN( A - B )
  2 >               ,  1, 'Aの方が大きい'
  3 >               , -1, 'Bの方が大きい'
  4 >               , '同じ大きさ'
  5 >        )
  6 > FROM DUAL ; 

これを実行した時、A の方が大きい値であれば、文字列"Aの方が大きい"
B の方が大きい値であれば、文字列"Bの方が大きい" が返ってきます。

このようにDECODE関数とSIGN関数が使いこなせるようになると、SQLの達人に一歩前進だ!