複雑なクエリの自己結合について

このQ&Aのポイント
  • 複雑なクエリの自己結合について説明します。自己結合を行う際にクエリが複雑になる場合、負荷を少なくする方法について考えます。
  • 自己結合を行いたいクエリが相関サブクエリを使用しているため、Viewが作成できない場合、クエリをスマートに自己結合する方法を模索します。
  • また、初めに自己結合や外部結合でデータを展開し、それを相関サブクエリなどで絞り込む手法も考えられます。質問者はこの方法が正しいのか迷っており、アドバイスを求めています。
回答を見る
  • ベストアンサー

複雑なクエリの自己結合について

はじめまして、SQLもMYSQLも初心者です。 独学で、1,2か月といったところでしょうか MYSQL5.5.を使用しています。 早速ですが質問です。 自己結合のもとになるクエリが複雑?な場合どうすれば負荷の少ないクエリが組めるでしょうか? 自己結合したいクエリが、相関サブクエリをつかっているためViewが作れないので 素人考えで、もととなるクエリをSQL中に何回も記述してみましたが、 メモリがオーバーフローしてしまいます。 複雑なクエリをスマートに自己結合する方法はないのでしょうか? それとも、そもそも、最初に自己結合や外部結合でめいいっぱいデータを展開し、それを相関サブクエリ.etcで、漸次、絞り込んでいくほうが、SQLの手段としては正しいのでしょうか? 他で上記のクエリのかなりの部分を使用するので、再利用できないかと思って組んでみましたが 行き詰まり、色々と自信がなくなってきました、アドバイスをお願いします。 以下やりたいことです 暇だったら見てください。 勉強も兼ね、カレンダーアプリで担当者ごとの抱えているプロジェクトと、忙しさ、割ける時間、効率性 を可視化することを目的としたソフトをつくろうと思っています。そこで、日にちごとに、不特定の時間帯から、時間の重複を許して、複数の時間帯を除した、あまりの時間を求めるクエリを組もうと思い、web上で勉強して、相関サブクエリと、自己結合とHAVING文などを組み合わせれば、実現可能なことがわかりました。そこで、相関図を書いて、実際に作って見たのですが、上記のようになった次第です。ぜひ、皆様のお知恵を拝借したいしだいです。よろしくお願いします。

  • sava1
  • お礼率100% (2/2)
  • MySQL
  • 回答数2
  • ありがとう数2

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

  • ベストアンサー
  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.2

データの結合は相乗的にデータが増えるので、自己結合などで 条件設定を冗長にやっていると処理時間が膨大になったり メモリを食い過ぎたりなど当然想定しなくてはいけませんね >独学で、1,2か月 で、このレベルの質問ができるとすると、相当基礎的なスキルがあるかとは 思いますが、まずはSQLの基本である正規化について知識を深めて、 インデックスなどをためしながらexplainでテストしていく というのが流れになると思います。 また簡易なデータ参照についてはエンジンも思い切ってMyISAMなどで 処理することで高速化をはかるとか、データ更新がおおくなかったり 完全なリアルタイム性が必要でないものは中間テーブルをつくって 高速化することはできるかと思います。 プロジェクト管理についてはガントチャートやパートチャートの考え方を理解し、 プロジェクトのパートごとに人月設定をしたうえで、アサインするユーザーに 配分の係数を掛けていくと進捗がだせると思いますので プロジェクトテーブル、ユーザーテーブル、プロジェクト=ユーザーアサインテーブル などに分けて処理すれば効率的にいけるかもしれません。 期間の処理はプロジェクトに寄せるか、さらに別テーブルで管理するかは 出力したい帳票によりますね

sava1
質問者

お礼

回答、そしてアドバイスありがとうございます。 >>完全なリアルタイム性が必要でないものは中間テーブルをつくって高速化 やっぱりそれしかないのですかね、テーブルを全更新しているとスピードが使用に耐えないので(explainでテストしてみるべきですけど) トリガつけて差分更新かぁ、そうするとデータの整合性が心配になってくるから、どこでどんなチェックをいれればいいのかなー。それに、メモリ制約結構外れて、汎用性あげられるよな、設計見直さな。むしろ仕様から変更したほうがいいのか? みたいな 全行程を自分一人でやる(さらに使用者(のうちの一人)も、保守も、利益を得るのも自分)特有の悩みが。むしろ贅沢な悩みかもしれませんがw 抜本的な仕様変更も視野に入れ考えてみます。 あと、ガントチャートいいですよね。 プロジェクトといっても少人数で、そんな複雑じゃなく、むしろ複数同時進行で、突発的に予定が入る という仕様上ガントチャートは考えておりませんでした、が余力があれば、インターフェース兼出力帳票として検討してみたいと思います。夢がひろがります、また、仕様が変わりそうですが。

その他の回答 (1)

回答No.1

MySQLはサブクエリに弱いという話を良く聞きます。 ※参考URLを貼っておきます。 私の場合、複雑な処理を書く場合は、後でメンテナンスする人の事も考えてなるべくシンプルに書く努力をします。 複雑なSQL文を使って一発で答えを得るより、簡素なSQLを複数回実行させたほうが、見た目にもキレイになるし、 後でのメンテナンスも楽になると思っているからです。 すみません、回答になっていないかも知れませんが・・・。

参考URL:
http://el.jibun.atmarkit.co.jp/garyotensei/2012/07/mysql-465d.html
sava1
質問者

お礼

早速の回答ありがとうございます。 >>MySQLはサブクエリに弱い indexの取り方がところどころおかしいとも聞きます、それも関係するのでしょうか。 webの評価を見ている限りフリーでは最強だと思うのですが、商用DBも考えたほうがいいのか。 >>後でメンテナンスする人の事も考え、なるべくシンプルに書く努力 >>複雑なSQL文を使って一発で答えを得るより、簡素なSQLを複数回実行させたほうが、見た目にもキレイになるし、後でのメンテナンスも楽になると思っているからです。 耳が痛いですw自分用に、ここまで集合を広げ、こういった特性関数で絞り込むみたいな設計で可視化は やってますが、後の人ことは考えてないです、精進します。

関連するQ&A

  • あるサイトの相関サブクエリの説明について

    いつもお世話になります。 相関サブクエリについて、教えて頂きたいことがあります。 以下のサイトに相関サブクエリについての説明がされています。 http://gihyo.jp/dev/serial/01/sql_academy2/000902 このサイトによると、 ----------------------------------------------------------------- 「行われている動作 リスト2の2つ目のSELECT文においても,最初に評価,実行されるのがサブクエリであるという点は変わりません。・・・」 ※リスト2  相関サブクエリ(性別による集合カット) SELECT * FROM Employees E1 WHERE age = (SELECT MAX(age) FROM Employees E2 WHERE E1.sex = E2.sex); ----------------------------------------------------------------- と説明があります。 理解できないのが、「最初に評価,実行されるのがサブクエリ」という内容です。 私の理解では、相関サブクエリは、内側のクエリが外側のクエリを参照するクエリのことで、まず外側のクエリが実行される。 その後、その結果の各レコードに対してサブクエリを実行していく、というように理解しています。 しかし、上記サイトでは先にサブクエリが実行されるという説明がされており、ちょっと混乱しています。 相関サブクエリは正しくはどういう挙動をするものなのでしょうか、また正しい説明がされているサイトなども教えて頂けないでしょうか。 宜しくお願いします。

  • mysql_queryの処理速度が遅い

    PHP+MySQLでプログラミングをしているのですが、実行時にmysql_queryの処理に時間がかかっています。状況は以下の通りです。 ・処理時間を計測するとmysql_queryの実行に15秒程度かかっています。 ・Webminで直接同じSQL文を実行すると1秒程度で終わります。 ・SQLのコマンドは単純なUPDATEです。 ・indexは設定してあります。 ・DBに格納してあるレコード数は数100件程度です。 ・optimizeは実行してみましたが、あまり効果はありませんでした。 お聞きしたいのはWebminで実行すると1秒程度で終わるSQL文がmysql_queryで実行すると、なぜ時間がかかるのかということです。 mysql_queryで時間がかかる原因およびmysql_queryの処理時間を短縮する方法などがあれば教えてください。 よろしくお願いします。

    • ベストアンサー
    • PHP
  • サブクエリではかけるのですが、サブクエリを使わないとできません。

    sql文について困っているので質問させてください。 以下のデータがあるとします。 番号  月日   金額 ---------------------------- 1    0512   100 1    0411   200 1    0310   300 2    0609   400 2    0708   500 2    0411   600 3    0523   700 3    0322   800 このデータを番号でグループ化し、 月日が最大のときの金額を取得したいです。 つまり、クエリの実行結果を以下のようにしたいです。 番号  月日   金額 ---------------------------- 1    0512   100 2    0708   500 3    0523   700 この場合、サブクエリを使って書けばほしい結果が得られると思いますが、 mysqlのバージョンが4.0.22なのでサブクエリが使えません。 サブクエリを使わないで上記の結果を得ることはできるのでしょうか? よろしくお願いします。

    • ベストアンサー
    • MySQL
  • 相関サブクエリの中で、グループ化はできない?

    いつもお世話になっています。 オラクルではないのですが、SQLの質問が多く感じたため、質問させていただきました。 タイトルの通り、相関サブクエリはグループ化した状態で行えるのか教えていただきたいんです。 課題は、売上表(Sales)から、売上数量(Quantity)の平均の10倍よりも売上数量(Quantity)の最大の方が大きい商品IDを見つけ出す。というものです。 考えたSQLは SELECT __S1.ProductID FROM __Sales AS S1 GROUP BY __ProductID HAVING __AVG(Quantity) * 10 < (SELECT    __MAX(Quantity)    FROM    __Sales AS S2    GROUP BY    __ProductID    HAVING    __S1.ProductID = S2.ProductID) です。考え方として 相関サブクエリで、現在の商品ID(HAVING S1.ProductID = S2.ProductIDのところ)の商品数量の最大値を比較として返そうと思いましたが、どうもうまくいきません。 こういった相関サブクエリは作れないのでしょうか?

  • 別サーバーのDB同士を結合することは可能でしょうか?

    お世話になっております。 MYSQL5を利用しております。 この度、別サーバーのDB同士を結合することは可能かどうか、もし可能であればサンプルを頂けないかと思い、投稿させて頂きました。 [現在使用しているDBサーバ] kagoyaサーバーのDB(MYSQL) sakuraサーバーのDB(MYSQL) [上記DBを結合させるコードを記述したファイルを置くサーバー] kagoyaサーバー 現在kagoyaサーバーにてそれぞれのDBからそれぞれのDBにアクセスして値を取得するところまでは出来ております。二回SQLを書いているのですが、これを一度でどうしても済ませたいと思い、JOINを使用して結合できないか調べてみました。 http://q.hatena.ne.jp/1178781253 http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1113186486?fr=rcmd_chie_detail 上記URLのように、同サーバー内なら可能のようですが、実際にやってみたのですが、「mysql_query($sql, $db);」の第二引数でどちらのDBに接続すればいいかわからず、両方試してみましたがダメでした。(自分が書いたソースを破棄してしまったためうろ覚えなのですが、返ってきたresource はresource #13でした。) 結局できるのかできないのかわからないままの状態です・・・。もしわかる方がいましたら、どうかご教授下さい!よろしくお願い致します!

  • MySQL SELECT文についての質問

    sql文について困っているので質問させてください。 以下のデータがあるとします。 番号  フィールド1   フィールド2 ------------------------------------ 1        0       あ 2        1       う 3        0       か 4        0       こ 5        1       た 6        0       ね 7        1       も 8        0       わ フィールド1が1で[あ行]であれば フィールド2が[あ行]である番号を取得し その件数を取得したいのです。 つまりクエリの実行結果を以下のようにしたいです。 番号  フィールド1   フィールド2 ------------------------------------ 1        0       あ 2        1       う 件数2件 mysqlのバージョンが4.0.22なのでサブクエリが使えません。 サブクエリを使わないで上記の結果を得ることはできるのでしょうか? よろしくお願いします。

    • ベストアンサー
    • MySQL
  • Accessで2種類のデータベースを結合する方法

    Accessで2種類のデータベースを結合する方法 AccessでMySQLとSQLServerというような2種類のデータベースをJOINしたSQLを使いたいと思います。 Access上でリンクしておいてクエリー定義すれば出来ることはわかっているのですが、高速化かつODBCの設定をしなくても済むように出来ればDAOを使って接続したいと思っています。 このような別データベースを結合するSQLは記述することは無理でしょうか? 又は別のリンクテーブルを使わなくても済む方法がありましたら、教えていただけると助かります。 Accessのバージョンは2007です。

  • MySQL + PHP 同じテーブルを対象にした複雑なクエリ

    こんばんは。 Mysql+php環境で、以下のようなテーブルを持っています。 ちょっと複雑な内容でクエリ結果を求めたいのですが、 うまい方法が見つからず、質問させて頂きます。 ―――――――――――――――― ▽ユーザーテーブル ―――――――――――――――― user_id |user_name 1 |タロウ 2 |ヨシコ 3 |シゲル 4 |マユミ ―――――――――――――――― ▽所有果物テーブル ―――――――――――――――― goods_id |goods_name |user_id 1 |パイン |1 2 |みかん |1 3 |メロン |1 4 |リンゴ |2 5 |みかん |2 6 |イチゴ |2 7 |グレープ |3 8 |イチゴ |3 9 |キウイ |3 10 |リンゴ |4 11 |みかん |4 12 |メロン |4 ―――――――――――――――― ▽出力したい条件 ―――――――――――――――― 自分(例えばマユミ)が所有している果物(goods)と、 いずれか同じものを持っている人(user)が 他に持っている果物(goods)を出したいが、 自分が既に所有しているものは除く。 ―――――――――――――――― 今回のデータと条件ですと、 同じものを持っているuserはタロウとヨシコで、 彼らが持っていてマユミが持っていない果物は 「パインとイチゴ」になります。 このような結果を出したいのですが、 これを出力するにはどのようなSQL文にすればよいでしょうか? 実際のデータはもっとレコード数が多いテーブルです。 サブクエリを駆使しても、どうも思った結果が出ず・・・ どうかお助け下さい。 宜しくお願いします。

    • ベストアンサー
    • PHP
  • Accessの内部結合

    こんにちは。 Accessでcateテーブルとgoodsテーブルがあります。 select * from goods inner join cate on goods.cateid = cate.id; クエリデザインで、テーブルとテーブルを結合して上記のようなSQLができました。 これは動作することを確認しました。 SQLビューで下記のようなSQLを書きました。 select * from goods inner join cate on left(goods.cateid,5) = cate.id; しかしながら、動きませんでした。 VBAを使わずに、Accessの標準のクエリデザインから上記のようなSQLを実行させることは可能でしょうか? クエリデザインでselect left(cateid,5) as cateid from goodsというTESTクエリをつくり、TESTクエリとcateテーブルとジョインさせれば解決しそうなことはわかるのですが・・・ 宜しくお願いします。

  • SQL Server7.0での特殊な結合演算子について

    最近、SQLServer7.0をいれて勉強しています。 http://www.techscore.com/tech/sql/index.html を参考に勉強しています。 そこの特殊な結合演算子の自然結合,指定結合ができません。 受注表、顧客表は「テーブルの結合」のところのテーブルを作成しました. NATURAL JOINの結合やON句を使う指定結合をやると 「列のプレフィックス '受注表' は、テーブル名と一致しないか、クエリ内の別名と一致しません」 というエラーがでます。WHERE句を使った結合だとできます。 何が問題なのでしょうか。 参考HPには「SQL92はある種の共通する結合操作を簡単に実行できるように、特別な構文を用意している」 とかいてあるですが、 SQLServer7.0にはバージョンが古すぎてSQL92がないってことなんでしょうか。 SQLServerをはじめたばかりなので、あまりくわしくないのですが、是非ともご教授よろしくおねがいします。