SQLでレコードの抽出方法と高速化について

このQ&Aのポイント
  • SQLでレコードの抽出方法や高速化の方法について教えてください。
  • ExcelのVBAを利用してOracleに接続し、必要なデータのみを抽出したいと考えています。現在はSQLを使用して目的のレコードを取得していますが、もっとシンプルかつ高速な方法があれば知りたいです。
  • テーブル「t1会議マスタ」と「t2会議履歴」があり、ある出席者を基に最新の会議の「会議名」「開催日」を取得したいです。現在のSQLでは抽出は成功していますが、もっと高速な方法があれば教えてください。
回答を見る
  • ベストアンサー

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などで抽出してもかまいません)。 よろしくお願いいたします。

  • Oracle
  • 回答数2
  • ありがとう数11

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

  • ベストアンサー
  • nda23
  • ベストアンサー率54% (777/1415)
回答No.2

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

kikitaiOK
質問者

お礼

>得られていません。 そうなんですか…検証不足です。 当方の環境でたまたま目的のレコードが表示されただけのようですね。 >WHERE 項目=(SELECT ~) は古い書式で、現在は JOIN句を使う方が普通です。 勉強になります。 JOIN句を使用した抽出…難解ですが頑張って勉強したいと思います。 今回は詳しい解説ありがとうございました。

その他の回答 (1)

  • nda23
  • ベストアンサー率54% (777/1415)
回答No.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

kikitaiOK
質問者

補足

さっそくの回答ありがとうございます。 このコードで0.08秒が0.06秒に改善されました。 ですが、『理解』ができませんでした。 日本語的に前から解釈して行くと、 (1)会議履歴から出席者CDで絞り込んだクエリ★2を作成 (2)「会議マスター」と「出席者CDで絞り込んだ最新の会議日のあるクエリ★3」を内部結合したクエリ★1を作成 (3)★1と★2を内部結合して目的のレコードを抽出 ということで間違いないでしょうか? なぜこのように複雑な処理をしているにもかかわらず高速なのかが理解できませんでした。 それに目的のレコードは(2)の時点で得られていますが、(2)だけではダメなのでしょうか? それと、基本的にWHERE句での抽出より内部結合によって目的のレコードを抽出するほうが高速ということでしょうか? WHERE F14開催日 = ★3のクエリ.最新日 としたほうがシンプルで早い気がしていたのですが…(初心者的には)

関連するQ&A

  • SQLで、過去で一番大きい日付のレコード抽出

    MySQLを使っています。 同じ商品のレコードが複数あります。 その多数のレコード中に、日付項目があります。そこから、 1)指定日に、2)一番近い過去の日の1件の、3)全商品のレコード、を抽出するには、 どのようなSQL文を書けばよいでしょうか? 1.過去に複数ある日付の中から、指定日に、一番近いレコード。 レコードの例) 指定日=2015-07-01 商品ID 日付 1 2015-10-11 ・・・未来 ⇒ 抽出せず 1 2015-08-02 ・・・未来 ⇒ 抽出せず 1 2015-07-01 ・・・指定日 ⇒ 抽出せず 1 2015-07-01 ・・・指定日 ⇒ 抽出せず 1 2014-01-01 ・・・過去 ⇒ 抽出せず 1 2015-06-03 ・・・過去 ⇒ 抽出したい★★ 2 2015-10-11 ・・・未来 ⇒ 抽出せず 2 2015-08-02 ・・・未来 ⇒ 抽出せず 2 2015-07-01 ・・・指定日 ⇒ 抽出せず 2 2014-01-01 ・・・過去 ⇒ 抽出せず 2 2015-06-03 ・・・過去 ⇒ 抽出したい ★★

    • ベストアンサー
    • MySQL
  • 【SQL】あるマスタのレコードに存在しない項目を取得する。

    下記のような2つのマスタがあるとします。 ・商品名マスタ 商品コード  商品名 - - - - - -  - - - - - - n01       ナス k01       カボチャ n02       ニンジン t01       タマネギ ・購入履歴マスタ 履歴連番  商品コード  購入日時 - - - - -   - - - - - -  - - - - - - 001     n01      2008-07-01 002     k01      2008-07-02 003     n01      2008-07-03 004     n01      2008-07-04 005     k01      2008-07-04 このとき、購入履歴マスタのレコードに存在しない商品を取得するSQLはどのように組み立てればよいでしょうか? 例えば上記例で言えば、下記のような結果を得ることが目的です。 商品コード  商品名 - - - - - -  - - - - - - n02       ニンジン t01       タマネギ 以上、よろしくお願いします。

  • SQLで、指定日に一番近いレコードだけ抽出

    Linuxサーバーで、MySQLを使っています。 商品テーブルの中で、 同じ商品のレコードが複数あります。 (例です。本来ならそんなつくりのテーブルは作らないです。) その多数のレコード中に、日付項目があります。 そこから、 1)商品毎に、2)指定日に、3)一番近い過去未来の日の、4)レコードだけを抽出するには、 どのようなSQL文を書けばよいでしょうか? 1.過去に複数ある日付の中から、指定日に、一番近いレコード。 2.未来に複数ある日付の中から、指定日に、一番近いレコード。 3.同一商品レコードは、複数抽出されない。

    • ベストアンサー
    • MySQL
  • SQLで抽出可能でしょうか?

    SQLで抽出可能でしょうか? Javaでツールを作成しています。 開発環境はjava 1.4、oracle 10gです。 処理の中にデータベースからレコードを取得する箇所があります。 10,000件のデータを保持する社員テーブル(syain_tbl)から 社員番号(syain_no)をキーに社員名(syain_name)を取得します。 現時点で作成したSELECT句は以下のとおりです。 select syain_no, syain_name from syain_tbl where syain_no in ('0001','0002','0003') 仮に'0001'と'0003'のレコードがあり、'0002'のレコードがない場合の結果は syain_no syain_name 0001 テスト太郎 0003 テスト三郎 となります。 ですが、実現したいことは 「条件に指定した社員番号のレコードがなかったとしても、結果として取得したい」です。 つまり求めたい結果としては syain_no syain_name 0001 テスト太郎 0002 (null) 0003 テスト三郎 です。 一時表を作成して外部結合させればうまくいきそうですが、 できればDDLなしで実現させたいです。 上記のSELECT句を修正して結果を求めることは可能でしょうか? (WHERE句にある社員番号をIN条件にしている箇所は、 一度に複数件のレコードを取得したいので変更はできません)

  • 検索にて抽出されたレコードをほかのテーブルに追加

    フォームで検索条件指定ご、マクロにて検索ボタンクリック時にフィルタ実行で、入力した条件と一致するものが抽出されるようになりました。 そこで抽出されたレコードをすでに作成してある検索履歴テーブルへ追加していき、あとでその履歴が見れるようにしたいのです。 イロイロ検索したところ、追加クエリを使用するように思うのですが、使い方が良くわからなく困っています。 詳しく教えてくれる方よろしくお願いします。 マクロのWhere条件は [姓フリガナ]=[Forms]![F照会]![姓検索] And [名フリガナ]=[Forms]![F照会]![名検索] And [生年月日]=[Forms]![F照会]![生年月日検索] 姓名フリガナ生年月日が一致するもの この抽出されたレコードのIDと、検索日を履歴としてのこしていきたいです。

  • アクセス フォーム上でのレコード抽出・ソート

    こんにちはアクセス2000で管理表をつくっています。 「工事マスタ」 工事ID、顧客ID、工事部門、契約日、請負額、追加額(以下略) 「顧客マスタ」 顧客ID、顧客名(以下略) などがあり、工事マスタを基にクエリAを作成し、 それをコントロールソースにもつフォームAを作成しました。 フォーム上のボタンやテキストボックスで レコードの抽出(フィルタ)を行いたいのですが いろいろ調べてみましたが、初心者なもので どう手をつけていいのかわからず困っています。 やりたいことは 1)工事部門(1・2)で、(1)のみのレコードを表示する その検索方法をコンボボックスでつくりたい 2)発注者名で検索をかけ、該当するレコードのみを表示する その検索方法をテキストボックスでつくりたい 3)契約日のソートをかける実行ボタンを配置したい 4)「請負額」「追加額」にそれぞれ消費税を計算して、その合計額「請負額+追加額+請負税+追加税」の《総合額》を自動計算しています。 その《総合額》の¥●●●~¥●●●という範囲に値するレコードを抽出したい です。 説明が足りない部分もあるかと思いますが どなたかご存知の方お知らせくださいませ。 また、参考サイトなども教えていただけると助かります。 どうぞよろしくおねがいします。

  • 重複レコードの抽出

    Windows Server 2003上で、SQL Server 2000を 使用しています。下記のようなSQLを作成したいのですが、知識不足のためご助力願いたいのですが。 テーブル名 test フィールド seihin (1項目のみ) seihinの構成  先頭4バイト 製品コード   後半4バイト 連番(0000~9999) やりたいこと seihinの重複するレコードを含む 製品コードに対しそのコード別の件数の算出 例 xxxx0002,xxxx0011,yyyy1111が複数件あるとき、 seihinコードがxxxxであるもの全体の件数及び yyyyであるもの全体の件数 なお、下記のSQLにて重複レコードの抽出とカウントはできていますが、それ以降がわかりません。 select seihin,count(seihin) as scount from test group by seihin having (count(seihin)>1) 以上よろしくお願いいたします。

  • SQLの抽出方法について

    あるテーブルに以下のカラムがあります。 店舗コード,売上日,金種コード,履歴番号,売上金額 プライマリキー(店舗コード~履歴番号) このテーブルには、店舗、売上日、金種コードごとの売上金額が履歴で管理されています。 ・データイメージ 0001,2004/04/01,01,0,1000 ・・・1行目 0001,2004/04/01,01,1,1100 ・・・2行目 0002,2004/04/01,02,0,500 ・・・3行目 0003,2004/04/01,03,0,2000 ・・・4行目 0003,2004/04/01,03,1,2010 ・・・5行目 0003,2004/04/01,03,2,1500 ・・・6行目 0001,2004/04/02,01,0,800 ・・・7行目      ・      ・ このデータから、売上日を指定して、 全店舗の金種ごとの履歴番号が最大のレコード(2,3,6行) を取得したいのですが、いいSQLが思いつかないので、ご存知の方教えてください。

  • SQL 特定のカラムが最大値のレコード取得

    初心者です。SQL文で困っています。 どなたかご教授頂けたらと思います。 環境は、SQL SERVER 2000です。 特定のカラムが最大値のレコードのみ取得したいです。 たとえば、以下のようなデータがあるとします。 コード、履歴番号で主キーとします。 コード|履歴番号 |金額 0001 | 1 | 12000 0001 | 2 | 12001 0001 | 3 | 12002 0002 | 1 | 12000 0002 | 2 | 12001 0002 | 3 | 12002 0003 | 1 | 12000 0003 | 2 | 12001 この場合に、コード毎に履歴番号が最大のレコードのみを取得したいです。 理想の結果は以下になります。 コード|履歴番号 |金額 0001 | 3 | 12002 0002 | 3 | 12002 0003 | 2 | 12001 以上です。よろしくお願いいたします。

  • SQLで条件にヒットしたレコードより後ろ10件を出したい

    データベースはOracleで、SQLでWhere区の条件にヒットしたレコードと、そのレコードより後ろ10件のレコードも抽出したい場合何か良い方法ありますか? 例.商品マスタがあって、商品CD=1111で検索した場合は、商品CDが1111より後ろ10件のレコードも抽出したい。 商品CDは連番になっていない部分もあります。