はじめに
今回の総集編では、前編、中編、後編、完結編に関連した内容を扱います。
対象読者
- SQLの可読性を向上させたい方
- SQLのパフォーマンスを向上させたい方
必要な環境
本稿で扱うSQLは、Oracle 10.2.0.1.0で動作確認しました。ソースコードはDB2 V9.5でも動作確認しました。その他、次の環境でも応用が可能です。
- Oracle9i以降
- DB2
- SQL Server 2005以降
1. 旅人算の感覚を応用する(2人旅人算)
旅人算は、有名な算数の問題です。旅人算の問題を解くには、複数の旅人を脳内でイメージする感覚が有効ですが、SQLで旅人算の感覚を応用できるのです。
本稿では、旅人算の感覚の使用例を2つ扱います。最初は、2人旅人算の感覚を応用したSQLです。
前編の「1. 歯抜けの最小値を探す」では、下記のselect
文を場合分けを行って検証しました。
select nvl(max(seq), 0) + 1 as gap from (select seq, Row_Number() over(order by seq) as Rank from SeqTbl) where seq = Rank;
上記のselect
文を、旅人算の感覚(2人旅人算)を使って検証してみましょう。速さが異なる2人の旅人(旅人R、旅人S)が数直線の原点からプラス方向に同時にスタートしたとして、
Row_Number() over(order by seq)
seq
と考えると、2人の旅人の位置の差は、広義の単調増加(大きくなるかそのまま)であると分かります。
そして、歯抜けが発生するなら、その位置は(2人の旅人が最後に同じだった位置)+1だと分かります。歯抜けが発生しなくても、同様に(2人の旅人が最後に同じだった位置)+1が求めるべき値となります。
SQLのイメージは下記となります。
seq Rank 2人の旅人の位置 --- ---- - 1- 2- 3- 4- 5- 6- 1 1 |SR| | | | | | 2 2 | |SR| | | | | 3 3 | | |SR| | | | 5 4 | | | | R|S | | 6 5 | | | | | R|S |
seq Rank 2人の旅人の位置 --- ---- - 1- 2- 3- 4- 5- 6- 1 1 |SR| | | | | | 2 2 | |SR| | | | | 3 3 | | |SR| | | | 4 4 | | | |SR| | | 6 5 | | | | | R|S |
seq Rank 2人の旅人の位置 --- ---- - 1- 2- 3- 4- 2 1 | R|S | | | 3 2 | | R|S | | 4 3 | | | R|S |
seq Rank 2人の旅人の位置 --- ---- - 1- 2- 3- 4- 5- 1 1 |SR| | | | | 2 2 | |SR| | | | 3 3 | | |SR| | | 4 4 | | | |SR| | 5 5 | | | | |SR|
seq Rank 2人の旅人の位置 --- ---- - 1- データなし | |