5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Laravel】条件付きサブクエリにはmergeBindingsを使おう

Last updated at Posted at 2019-09-20

Laravelのクエリビルダーで条件付きサブクエリをDB::raw()を使用してjoinをした時にInvalid parameter numberとなったので、対処方法をまとめます。

こちらの記事はブログでも公開しています。

Where句のバインド値をマージしないとエラーになる

試しに以下のようなSQLをクエリビルダ ーのDB::raw()を使用して実装していきたいと思います。

select * from (
    -- サブクエリ1
    select * from table1 where status = 'Success'
) as s1
left join (
        -- サブクエリ2
    select * from table2 where status = 'New'
) as s2 on s1.id = s2.relid
where t.id = 1

定義したサブクエリをtoSql()でSQL文を生成して、DB::rwa()を使用して組み立てていきたいと思います。

        // サブクエリ1
        $subquery1 = \DB::table('table1')
            ->where('status', '=', 'Success');
        // サブクエリ2
        $subquery2 = \DB::table('table2')
            ->where('status', '=', 'New');

        $query = \DB::table(\DB::raw("({$subquery1->toSql()}) as s1"))
            ->leftjoin(\DB::raw("({$subquery2->toSql()}) as s2"), function($join){
                $join->on('s1.id', '=','s2.relid');
            })
        ->where('t.id', '=', 1);
        $data = $query->get();

実際に実行をする以下のようにparameterのエラーが発生します。これはサブクエリをtoSql()でSQLを生成してもバインドした値は含まれないないのが原因です。

"SQLSTATE[HY093]: Invalid parameter number (SQL: select * from (select * from `table1` where `status` = 1) as s1 left join (select * from `table2` where `status` = ?) as s2 on `s1`.`id` = `s2`.`relid` where `s1`.`id` = ?) "

mergeBindingsを使用してバインド値を追加する

mergeBindings()を使ってバインド値をマージしていきます。
マージする順番も気をつける必要がありますので注意してください。

        $subquery1 = \DB::table('table1')
            ->where('status', '=', 'Success');
        $subquery2 = \DB::table('table2')
            ->where('status', '=', 'New');
        $query = \DB::table(\DB::raw("({$subquery1->toSql()}) as s1"))
            ->leftjoin(\DB::raw("({$subquery2->toSql()}) as s2"), function($join){
                $join->on('s1.id', '=','s2.relid');
            })
            ->mergeBindings($subquery1)
            ->mergeBindings($subquery2)
        ->where('t.id', '=', 1);
        $data = $query->get();
5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?