私がCodeigniterでサブクエリを使ったSQLを書くときの方法

2018年3月2日

環境

Codeigniter : 3.1.7

 

はじめに

CodeigniterにはQuery Builderがあり、ある程度の事は対応することができます。
しかし下記のようなものに上手く対応できません。


SELECT 
 *
FROM
 table1
WHERE
 flg = 1
AND
( 
  access1 LIKE '%A%'
 OR
  access2 LIKE '%A%'
 OR
  access3 LIKE '%A%'
)

お判りでしょうか?

例えば店舗を探す時に、
公開フラグ(flg )が1で、
アクセス情報(access)のどこかに検索対象の文字が存在している店舗を探すとします。

 

その場合、$this->db->or_like()などを使うと下記SQLになってしまいます。

 
SELECT
 * 
FROM
 table1 
WHERE
 flg = 1
OR
 access1 LIKE '%A%' 
OR
 access2 LIKE '%A%' 
OR
 access3 LIKE '%A%'

これですと、公開フラグ(flg )が0の店舗も引っかかってしまいますし、
検索条件が無くても、公開フラグ(flg )が1なら引っかかります。

 

力技でやる方法もありますが・・・

$esc_str =  $this->db->escape_like_str('A');
$this->db->where("WHERE flg = 1 AND (access1 LIKE '%{$esc_str}%' ESCAPE '!' OR access2 LIKE '%{$esc_str}%' ESCAPE '!'  OR access3 LIKE '%{$esc_str}%' ESCAPE '!' )", NULL, FALSE);  

正直キツイっす・・・

 

 

サブクエリを使う

私はQuery Builderで対応できない状況にぶち当たった時、サブクエリで対応してます。

Query Builderを使用しつつサブクエリを取得するには以下のようなやり方をします。

// 読み込み
$subquery_init = $this->load->database('', TRUE);

$subQuery = $subquery_init->select('no', FALSE)
              ->from('table')
              ->or_like(array(
                   'access1' => 'A',
                   'access2' => 'A',
                   'access3' => 'A'
                    ))
              ->get_compiled_select();

// 初期化
$subquery_init->reset_query();

 

上記で作ったサブクエリを利用して


$this->db->where("no IN {$subQuery}", NULL , FALSE);

 

みたいな形でSQLが書けます。

若干遅くなるかもしれませんが、後々の追加修正等に対応しやすいのでおすすめです。

 

今日はこの辺でー

  • この記事を書いた人

カバノキ

印刷会社のWEB部隊に所属してます。 WEB制作に携わってから、もう時期10年になります。 普段の業務では、PHPをメインにサーバーサイドの言語を扱っています。 最近のお気に入りはJavascriptです。 Vue.jsを狂喜乱舞しながら、社内に布教中です。

-CodeIgniter
-,