スポンサーサイト

0

    一定期間更新がないため広告を表示しています


    • 2014.12.23 Tuesday
    • -
    • -
    • -
    • -
    • -
    • by スポンサードリンク

    Doctrine(1.x)でのLEFT OUTER JOIN実現方法

    0
       公式のドキュメント
      http://www.doctrine-project.org/projects/orm/1.2/docs/manual/dql-doctrine-query-language/ja#join%E3%81%AE%E6%A7%8B%E6%96%87:on%E3%82%AD%E3%83%BC%E3%83%AF%E3%83%BC%E3%83%89
      によると、ONキーワードでリレーション条件がカスタム指定できるようなことが書いてありますが、実際には効きませんorz

      試行錯誤の末、無理やりLEFT OUTER JOINぽいことを実行させることができたので忘れないようにメモ。
      実験しながらエラーMSGでググると、symfony公式のフォーラムでも世界各国の方々がLEFT OUTER JOINができないと悩んでいた。

      なんでONを自分で指定したいかと言うとモデルを次のように定義してあるとして、
      Able:
      columns:
      id: { type: integer(1), primary: true }
      Baker:
      columns:
      id: { type: integer(1), primary: true }
      out_class: string(4)
      out_id: integer(1)
      Cat:
      columns:
      id: { type: integer(1) }
      Bakerはout_classの値によりAbleかCatどちらかにJOIN先が変わります。
      なんでこんな変な構造にするか詳細は聞かないでください(笑

      【実験1】
      まず公式のドキュメント通りに。
      $q = Doctrine::getTable("Baker")->createQuery("b")->leftJoin("Able a ON a.id ON b.out_id");
      ⇒...FROM Baker b, Able a...
      ONどこいった??単にFROMにカンマ区切りで入れられると、SQL側でAble.idとBaker.idで勝手にJOINされちゃって都合が悪い。

      【実験2】
      公式ドキュメントにWITHというのも書いてあるので使ってみた。
      $q = Doctrine::getTable("Baker")->createQuery("b")->leftJoin("Able a ON a.id =b.out_id");
      ⇒...FROM Baker b, Able a...
      WITHどこいった??

      【実験3】
      無理を承知でINNER JOINにしてみる。Linux系OSのMySQLで、MyISAMテーブル(=外部キー制約なし)だとBaker.out_idとA.idのINNER JOINとか普通に成立した記憶が。
      $q = Dcotrine::getTable("Baker")->createQuery("b")->innerJoin("Able a ON a.id = b.out_id");
      ⇒エラー。AbleとBakerの間にリレーションが定義されてないとか何とか。まあ当然。


      ここで公式APIドキュメントを読みに行く。
      Doctrine_Query_Abstruct::leftJoin($join, $params=array())
      色々場合分けはあるが、要は最後に $this->dqlQueryPart['from']に 'LEFT JOIN '.$joinをセットする仕組みのよう。
      【実験4】
      とりあえずセットした後にちゃんとセットされているかどうかチェックしてみる。
      $q = Doctrine::getTable("Baker")->createQuery("b")->leftJoin("Able a ON a.id = b.out_id");
      var_dump($q->getDql());
      ⇒FROM Baker b LEFT JOIN Able a ON a.id = b.out_id
      ちゃんとDQLにはセットされていることが確認できた。
      が、$q->getSqlQuery()すると相変わらず FROM Baker b, Able aのみ。どうやらDQLからSQLを生成する時にONが無視されてしまう様子。

      ここでふと思い出した。Pear::DBを使ってSQLを勉強し始めた頃、FROMにテーブルを羅列してWHEREでJOIN条件書いてもほしいデータが取れてたなー。その後SQL実行速度の問題でちゃんとJOINを書くようになったんだけど。
      【実験5】
      だめもとで。
      $q = Doctrine::getTable("Baker")->createQuery("b")->addFrom("Able a")->addWhere("b.out_id = a.id");
      ⇒実験3と同じエラー。でも、$q->getSqlQuery()ではちゃんとSQLが出て来るし、それをコピペしてphpmyadminに実行させたらちゃんと想定通りのデータが出た。

      【実験6】
      実験5ではAbleのデータを入れるコンポーネント(プロパティ)がないよ!って怒られてる気がしてきた。同時にBakerとJOINするAbleまたはCatのデータはBakerに取得用のメソッドを作ってあるのでAbleのデータを最初のSELECTで取らなくてもいいよね、と考える。
      $q = Doctrine::getTable("Baker")->createQuery("b")->addFrom("Able a")->addWhere("b.out_id = a.id")->select("b.*");
      ⇒成功!!

      ここまで来るのに休み休み(家事育児やりながら^^;)で4時間近くかかってしまった(汗
      【結論】
      スマートじゃない&MySQLエンジンがんばって!なSQLだけど、上記の方法でLEFT OUTER JOINっぽいことはできることがわかりました。



      スポンサーサイト

      0

        • 2014.12.23 Tuesday
        • -
        • 15:20
        • -
        • -
        • -
        • -
        • by スポンサードリンク

        コメント
        コメントする








           
        この記事のトラックバックURL
        トラックバック

        PR

        calendar

        S M T W T F S
             12
        3456789
        10111213141516
        17181920212223
        24252627282930
        << September 2017 >>

        twitter

        selected entries

        categories

        archives

        recent comment

        • 結局CodeIgniter用汎用Modelクラス&汎用CRUDスクリプトを書きました
          プログラマー
        • icu4.4以上が用意できないサーバーでSymfony2.3以上を使う方法
          よし
        • icu4.4以上が用意できないサーバーでSymfony2.3以上を使う方法
          ななうぇぶ
        • icu4.4以上が用意できないサーバーでSymfony2.3以上を使う方法
          よし
        • icu4.4以上が用意できないサーバーでSymfony2.3以上を使う方法
          よし
        • WindowsのPCで開発するphperがxhprofを使う方法
          ななうぇぶ
        • WindowsのPCで開発するphperがxhprofを使う方法
          川本
        • [バッドノウハウ]Symfony2で別テーブルの集計項目を一覧に含めたいとき
          よし
        • Symfony Advent Calendar JP 2012 day 14 - vendorをcomposerで管理しているプロジェクトにcomposerを使わずにバンドルを追加したときのautoloadの書き方
          77web
        • Symfony Advent Calendar JP 2012 day 14 - vendorをcomposerで管理しているプロジェクトにcomposerを使わずにバンドルを追加したときのautoloadの書き方
          ktz

        recent trackback

        • HTMLの表(TABLE)のセル(TD)に斜線を引くjavascriptライブラリ slash.js 作っちゃいました
          常山日記
        • django対symfony 日本語メール送信(その1 symfony編)
          CPA-LABテクニカル
        • CodeIgniterでユーザー認証
          されどLAMPな日々
        • 久々にdjangoを最新版にしたらHTMLがエスケープされちゃった!!(解決済み)
          常山日記
        • FastCGIを諦めてmod_pythonを使う。Apacheのアップグレード
          サーバー用語集
        • さくらインターネット、sqlite3でdjango@CGI版を使う際の設定メモ
          常山日記
        • さくらインターネット スタンダードプランでdjango使ってる方、DBは?
          mitszoの日記
        • python多次元リストをsort(並べ替え)する方法?
          mitszoの日記
        • フォームから送信した値とrequest.POSTの挙動($_POST@PHPとの比較)
          Humming Via Kitchen
        • 日本語テキストをtruncate@django(Python全般にも??)
          常山日記

        recommend

        links

        profile

        search this site.

        others

        mobile

        qrcode

        powered

        無料ブログ作成サービス JUGEM