SQLの窓 イラストAC フリー素材

2009年06月30日

グループ関数の原則

グループ関数の原則

一応 Oracle をベースとしてのお話です。

一番の大原則は、group by で指定された列のみが select で そのまま記述できるというところです。
テーブルは通常正規化されていますから、コードに対する名称は別テーブルある事になります。
ですから、結合して名称を取り出して、その結果を:結合したキーで group by に指定した場合、
キーと名称は一対一ですが、SQL からすれば select に指定できるのは キーのほうだけです。

この場合、どうしてもその場で名称が欲しい場合は max 関数を使いますが、全体としての解決策
はいくつかあります。しかし、とりあえずこの大原則を中心に考えます。

そもそも。

select 表示データリストfrom テーブル名 と group by グループ列 と order by は、データを
処理するプロセスが違います。元のデータに直接アクセスするのが from テーブル where 条件
で、group by グループ列 having 条件は、加工処理です。order by は全ての処理が終わった後の
単純なソート処理です。

select 表示データリスト は、出力フォーマットと考えれば良いでしょう。

そう考えた場合、グループ列( 複数もあります ) を中心に加工された出力結果が仮想的なテーブル
として提供されるのが group by の結果です。グループ列 以外はグループ関数を通して出力する
ように仕様で決められていますし、それ以外の方法は矛盾が生じます( 特例とか無いので )

とまあ、理屈をこねるより group by  のやってる事を自分でかわりにやってみれば解る事で、
コントロールプレイクで集計して最大値や最小値や平均やら求めるアルゴリズムは標準化できても、
はたしてただ表示したいが為に、対象となるキーにデータを付加するのは・・・
実際は、そのデータの為に保存エリアを用意する事になりますが、その時だけの都合的処理で、
仕様としての必然性に欠けますよね。


でまあ、この話はこれくらいで。


もう一つ原則的というか、騙されやすい仕様というか、グループ関数と NULL の関係です。
これは、間違いやすい落とし穴で、 NULL 同士の演算が NULL になるという SQL の原則に
のっとった上での グループ関数の挙動ですが、全て「その行は無視」が原則です。

例外は count( * ) で NULL を含む全ての行。 count( 列名 ) は NULL を除く行数。
count( distinct 列名 ) は、列名が重複しない数( つまり種類の取得 )
その他も NULL の行は無視されますが、以下は注意です。

sum( 給与 + 手当 ) 

給与はともかく、手当は NULL を含むという場合が想定される場合、給与 NULL は 基本給
ですから、その値が NULL という事は理由があって計算に入れる必要が無いのは矛盾しませんが、
手当が NULL の場合、給与+手当が NULL になって、計算が除外されてしまいます。
ですから、以下のように書く必要があります。

sum( 給与 + nvl( 手当,0 ) )

ですが、現実的には結局給与にも nvl しておいたほうが痛い目を見なくて済むと思います。



【DB関連の最新記事】
posted by at 2009-06-30 21:03 | DB関連 | このブログの読者になる | 更新情報をチェックする