CodeZineに掲載されたSQLを分析関数で記述する 6
山岸賢治 [著] 2008/10/31 14:00

SourceCode 3.03 KB

 SQLを使う業務では分析関数を使いこなすと、生産性とSQLの可読性とパフォーマンスを、大きく向上させることができます。分析関数を使う際の考え方と、処理のイメージを解説します。今回の応用編では、分析関数の変わった使い方を紹介します。

1 2 3 4 →

はじめに

 今回の応用編では、分析関数の変わった使い方を紹介します。

対象読者

  • SQLの可読性を向上させたい方
  • SQLのパフォーマンスを向上させたい方

 2問目で3値倫理に関連する問題を、4問目でcase式に関連する問題を取り上げますので、3値論理とNULLCASE式のススメ(前編)を先に読んでおくと理解が進むと思います。

必要な環境

 本稿で扱うSQLは、Oracle 10.2.0.1.0で動作確認しました。ソースコードはDB2 V9.5でも動作確認しました。その他、次の環境でも応用が可能です。

  • Oracle9i以降
  • DB2
  • SQL Server 2005以降

1. 複数列のdistinctなcount

 最初は、複数列のdistinctcountを求めるSQLです。まずは、テーブルのデータと、出力結果を考えます。

IDTable
IDColAColB
1abc
2abc
3ab
4ab
5ab

 ColA,ColBの組み合わせのdistinctcountを求めます。(ColA,ColB) = (ab,c),(a,bc),(a,b)で3通りの組み合わせがあるので、これをdiscntとして下記の形で出力します。

出力結果
IDColAColBdiscnt
1abc3
2abc3
3ab3
4ab3
5ab3

 下記は、残念ながら文法エラーとなります。count関数で2つ以上の引数の指定は認められていないのです。

文法エラー
select ID,ColA,ColB,
count(distinct ColA,ColB) over() as discnt
  from IDTable;

 どうにかして引数を1つにまとめようということで、文字データとしてのカンマが存在しないならば、カンマを区切り文字に使って文字を連結させた下記のSQLでもいいでしょう。

カンマを区切り文字に使う方法
select ID,ColA,ColB,
count(distinct ColA || ',' || ColB) over() as discnt
  from IDTable
order by ID;

 しかし、上記のSQLではColAとColBが数値型や日付型だった場合に、文字型にキャストしないと暗黙キャストが発生します。

 そこで、別解として下記の逆ソートを使うSQLがあります。count関数で2つ以上の引数の指定はできませんが、dense_rank関数であれば、2つ以上の引数を指定できるのです。

逆ソートを使う方法
select ID,ColA,ColB,
-1+dense_rank() over(order by ColA asc ,ColB asc )
  +dense_rank() over(order by ColA desc,ColB desc) as discnt
  from IDTable;

 order by ColA asc,ColB ascでのascは省略可能ですが、descと対比させたほうが分かりやすいと考え、省略していません。

 下記の数式をふまえてdense_rank関数を使っています。-1を加算しているのは、自分を2回数えているからです。

-1 + 重複を除いた自分以上の組み合わせの数
   + 重複を除いた自分以下の組み合わせの数
= 重複を除いた組み合わせの数

 下記SQLの結果を考えると理解しやすいでしょう。

select ID,ColA,ColB,
dense_rank() over(order by ColA asc ,ColB asc ) as Rn,
dense_rank() over(order by ColA desc,ColB desc) as RevRn,
-1+dense_rank() over(order by ColA asc ,ColB asc )
  +dense_rank() over(order by ColA desc,ColB desc) as "-1+Rn+RevRn"
  from IDTable
order by ID;
SQLの結果
IDColAColBRnRevRn-1+Rn+RevRn
1abc313
2abc223
3ab133
4ab133
5ab133

1 2 3 4
→
INDEX
分析関数の衝撃6(応用編)
Page1
はじめに
対象読者
必要な環境
1. 複数列のdistinctなcount
2. range指定のcount関数
3. 次の入社日を求める
4. case式とignore nullsオプション
最後に
参考資料
プロフィール
山岸賢治 ヤマギシケンジ

Oracle ACEの1人。
OracleSQLパズルの運営者。
ORACLE MASTER Silver Oracle Database 10g
(研修受講で)ORACLE MASTER Gold Oracle Database 10g
ソフトウェア開発技術者 (情報処理技術者試験)
第二種情報処理技術者 (情報処理技術者試験)
 


記事へのコメント・トラックバック機能は2011年6月に廃止させていただきました。記事に対する反響はTwitterやFacebook、ソーシャルブックマークサービスのコメントなどでぜひお寄せください。

スポンサーサイト