この自己結合の場合も,
リスト4 説明用:非集約の状態で取ると
SELECT LS0.sample_date AS cur_date,
LS1.sample_date AS latest
FROM LoadSample LS0
LEFT OUTER JOIN LoadSample LS1
ON LS1.sample_date < LS0.sample_date;
図2 リスト4の実行結果
cur_date latest -------- -------- 08-02-01 ← S0:2月1日より小さい日付は 1つもないので,0個 08-02-02 08-02-01 ← S1:2月2日より小さい日付は1個 08-02-05 08-02-01 ← S2:2月5日より小さい日付は2個 08-02-05 08-02-02 08-02-07 08-02-01 ← S3:2月7日より小さい日付は3個 08-02-07 08-02-02 08-02-07 08-02-05 08-02-08 08-02-01 ← S4:2月8日より小さい日付は4個 08-02-08 08-02-02 08-02-08 08-02-05 08-02-08 08-02-07 08-02-12 08-02-01 ← S5:2月12日より小さい日付は5個 08-02-12 08-02-02 08-02-12 08-02-05 08-02-12 08-02-07 08-02-12 08-02-08
このように,
S0~S5の部分集合は,
という包含関係のある部分集合群です
現在の日付の処理量と,
リスト5 処理量も併せて表示する
SELECT LS0.sample_date AS cur_date,
MAX(LS0.load_amt) AS cur_load_amt,
MAX(LS1.sample_date) AS latest,
(SELECT MAX(load_amt)
FROM LoadSample
WHERE sample_date = MAX(LS1.sample_date)) AS latest_load_amt
FROM LoadSample LS0
LEFT OUTER JOIN LoadSample LS1
ON LS1.sample_date < LS0.sample_date
GROUP BY LS0.sample_date;
図4 リスト5の実行結果
cur_date cur_load_amt latest latest_load_amt ---------- --------- ---------- ----------- 2008-02-01 1024 2008-02-02 2366 2008-02-01 1024 2008-02-05 2366 2008-02-02 2366 2008-02-07 985 2008-02-05 2366 2008-02-08 780 2008-02-07 985 2008-02-12 1000 2008-02-08 780
ただし注意が必要なのは,
そこで代替案として,
リスト6 最大下界を求めるロジックをWHERE句に記述
SELECT LS0.sample_date AS cur_date,
LS0.load_amt AS cur_load,
LS1.sample_date AS latest,
LS1.load_amt AS latest_load
FROM LoadSample LS0
LEFT OUTER JOIN LoadSample LS1
ON LS1.sample_date = (SELECT MAX(sample_date)
FROM LoadSample
WHERE sample_date < LS0.sample_date);
これも結果は先ほどと同じになります
- 注3)
- 反対概念はもちろん
「最小上界」 (least upper bound) です。非等値結合の不等号の向きを逆にして, MIN関数を使うことで取得できます。練習として試してみてください。 - 注4)
- 「⊃」
は集合の包含関係を表す記号で, たとえば 「哺乳類⊃人類」 のように使います。今, S0~S5は, 大きな数字の集合が小さな数字の集合をすっぽり含む構造になっています (S0は空集合ですが, 空集合は定義上すべての集合に含まれるとされるので, やはりS1~S5のすべてに含まれます)。 - 注5)
- この再帰集合の理論的背景については,
『指南書』 「1-2 自己結合の使い方」 および 「2-7 SQLと再帰集合」 で詳細に取り上げたので, そちらも参照のほど。 - 注6)
- この一見すると構文違反に見える
(でも適法な) SQLの論理的な背景については, 『指南書』 の 「2-10 SQLにおける存在の階層」 を参照。 - 注7)
- Oracle 10gでは,
外部結合の条件にサブクエリを指定できないという制限があるため, このクエリは動作しません。その場合は内部結合に変える必要がありますが, そうすると今度は現在の日付が 「2008-02-01」 の行が結果に現れないという不便が生じます。悩ましいものです。ほかの実装にはこういう不都合はありません。