こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

SQLでのレコードの抽出について。

SQLでのレコードの抽出について。
ExcelのVBAを利用してOracleに接続し、必要なデータのみを抽出したいと考えています。
目的のレコードの抽出じたいには成功しているのですが、
他にも多数の処理を前後で行うのでなるべく高速に処理ができればと考えています。
そこでSQL、VBに詳しい方に作成したコードを見ていただき、もっと高速に処理ができるよう
ご教授していただければと思います。

前置きが長くなりましたが、以下に作成したSQLと状況を記載します。

テーブル : t1会議マスタ
フィールド: f11部門コード、f12会議NO、f13会議名、f14開催日、その他…

テーブル2 : t2会議履歴
フィールド: f21部門コード、f22会議NO、f23出席者CD、その他…

というテーブルがあり、ある出席者をもとに
その出席者が出席した一番新しい会議の「会議名」「開催日」を取得したいのです。

そこでSQLを作成し、目的のレコードのみを表示するよう作成したのが以下のものです。
SELECT t1会議マスタ.f14開催日 t1会議マスタ.f13会議名
FROM t1会議マスタ INNER JOIN t2会議履歴
ON t1会議マスタ.f11部門コード = t2会議履歴.f21部門コード
AND t1会議マスタ.f12会議NO = t2会議履歴.f22会議NO
WHERE t1会議マスタ.f14開催日
IN (
SELECT MAX(t1会議マスタ.f14開催日)
FROM t1会議マスタ INNER JOIN t2会議履歴
ON t1会議マスタ.f11部門コード = t2会議履歴.f21部門コード
AND t1会議マスタ.f12会議NO = t2会議履歴.f22会議NO
WHERE t2会議履歴.f23出席者CD = (変数)
  AND t2会議履歴.f21部門コード = (???)
)
GROUP BY t1会議マスタ.f14開催日, t1会議マスタ.f13会議名

以上です。
もっとシンプルかつ高速に行えればと思います(SQLで完全に絞り込まなくてももっと早い方法があればVBAなどで抽出してもかまいません)。
よろしくお願いいたします。

投稿日時 - 2010-07-25 00:06:19

QNo.6061965

暇なときに回答ください

質問者が選んだベストアンサー

解釈は合っています。
>それに目的のレコードは(2)の時点で得られていますが
得られていません。(2)は最新日に開かれた会議を日付
だけで抽出しています。対象者の出席していないものも
含まれている可能性があります。
WHERE 項目=(SELECT ~) は古い書式で、現在は
JOIN句を使う方が普通です。

投稿日時 - 2010-07-27 16:46:51

お礼

>得られていません。
そうなんですか…検証不足です。
当方の環境でたまたま目的のレコードが表示されただけのようですね。

>WHERE 項目=(SELECT ~) は古い書式で、現在は
JOIN句を使う方が普通です。
勉強になります。
JOIN句を使用した抽出…難解ですが頑張って勉強したいと思います。

今回は詳しい解説ありがとうございました。

投稿日時 - 2010-07-28 21:06:32

ANo.2

このQ&Aは役に立ちましたか?

10人が「このQ&Aが役に立った」と投票しています

回答(2)

ANo.1

先ず、SQLの問題ですね。
考え方を整理し、構造化しないとSQLは作れません。
(1)t2会議履歴の特定人物と結合する
  t1会議マスタの最大日付を取得する。
(2)上記(1)と同じ開催日のt1会議マスタを抽出する。
(3)上記(2)と特定人物で絞ったt2会議履歴を結合する。

SQLは英語なので、後から書きます。

SELECT A.f13会議名,A.f14開催日 FROM
(SELECT C.f13会議名,C.f14開催日,C.f11部門コード,C.f12会議NO
FROM t1会議マスタ C INNER JOIN
(SELECT MAX(E.f14開催日) 最新日 FROM t1会議マスタ E
INNER JOIN t2会議履歴 F
ON E.f11部門コード=F.f21部門コード
AND E.f12会議NO=F.f22会議NO
WHERE F.f23出席者CD='****' /* ★コードは文字型と解釈 */
GROUP BY F.f23出席者CD) D
ON C.f14開催日=D.最新日) A
INNER JOIN
(SELECT f21部門コード,f22会議NO FROM t2会議履歴
WHERE f23出席者CD='****') B
ON A.f11部門コード=B.f21部門コード
AND A.f12会議NO=B.f22会議NO

ちょっと分かり難いので、ブロック化してみます。
最終形は以下のようになっています。
SELECT A.f13会議名,A.f14開催日 FROM (★1) A
INNER JOIN (★2) B
ON A.f11部門コード=B.f21部門コード
AND A.f12会議NO=B.f22会議NO

★2は特定人物を抽出したクエリで、最後にあるものです。
(SELECT f21部門コード,f22会議NO FROM t2会議履歴
WHERE f23出席者CD='****') B

★1は(2)の抽出で、部分的には以下のようになっています。
SELECT C.f13会議名,C.f14開催日,C.f11部門コード,C.f12会議NO
FROM t1会議マスタ C INNER JOIN (★3) D
ON C.f14開催日=D.最新日

★3は特定人物が出席した会議の最新日を得るクエリです。
SELECT MAX(E.f14開催日) 最新日 FROM t1会議マスタ E
INNER JOIN t2会議履歴 F
ON E.f11部門コード=F.f21部門コード
AND E.f12会議NO=F.f22会議NO
WHERE F.f23出席者CD='****'
GROUP BY F.f23出席者CD

投稿日時 - 2010-07-25 12:05:38

補足

さっそくの回答ありがとうございます。
このコードで0.08秒が0.06秒に改善されました。
ですが、『理解』ができませんでした。
日本語的に前から解釈して行くと、
(1)会議履歴から出席者CDで絞り込んだクエリ★2を作成
(2)「会議マスター」と「出席者CDで絞り込んだ最新の会議日のあるクエリ★3」を内部結合したクエリ★1を作成
(3)★1と★2を内部結合して目的のレコードを抽出
ということで間違いないでしょうか?

なぜこのように複雑な処理をしているにもかかわらず高速なのかが理解できませんでした。
それに目的のレコードは(2)の時点で得られていますが、(2)だけではダメなのでしょうか?

それと、基本的にWHERE句での抽出より内部結合によって目的のレコードを抽出するほうが高速ということでしょうか?
WHERE F14開催日 = ★3のクエリ.最新日
としたほうがシンプルで早い気がしていたのですが…(初心者的には)

投稿日時 - 2010-07-26 15:39:55

あなたにオススメの質問