MT5のPHP APIを探る(その4)

「MT5のPHP APIを探る」の第4回をお送りします。
今回は、複数のテーブルを結合する方法を紹介します。

1.複数のテーブルの結合

一連の記事の「その2」に、結合の条件を指定する方法を書きました。
複数のテーブルを結合する場合、その書き方を拡張して、結合方法を表す配列を複数回書きます。

例えば、IDが2番のブログから、「お知らせ」というカテゴリに属するブログ記事(かつ公開されている記事)を、日付の新しい順に読み込みたいとします。
この場合、以下の2つの条件で結合を行い、かつカテゴリ名(category_labelフィールド)の値が「お知らせ」という条件を指定します。

  • mt_entryテーブルのentry_idフィールドと、mt_placementテーブルのplacement_entry_idフィールドが等しい
  • mt_placementテーブルのplacement_category_idフィールドと、mt_categoryテーブルのcategory_idフィールドが等しい

結合と検索条件を指定する部分のプログラムを書くと、以下のようになります。

$extras['join'] = array(
    'mt_placement' => array(
        'condition' => 'placement_entry_id = entry_id'
    ),
    'mt_category' => array(
        'condition' => 'placement_category_id = category_id'
    )
);
$where = <<< HERE
entry_blog_id = 2
and entry_status = 2
and category_label = 'お知らせ'
order by entry_authored_on desc
HERE;
require_once('lib/class.mt_entry.php');
$_entry = new Entry;
$entries = $_entry->Find($where, false, false, $extras);

2~4行目と、5~7行目で、前述の2つの結合条件を順に指定しています。
そして、12行目でカテゴリ名(category_labelフィールド)の値が「お知らせ」という条件を指定しています。

2.同じテーブルを複数回結合する

場合によっては、同じテーブルを2回以上結合し、それぞれで別々の検索条件を指定したいこともあります。
SQLでこのようなことを行うには、それぞれのテーブルに別名を付けて区別します。

MT5のPHP APIでも、テーブルに別名を付けることができます。
その場合、連想配列で結合条件を指定する際に、テーブル名の後に別名を書きます。
また、一般のSQLと同様に、フィールドを「テーブルの別名.フィールド名」のように指定します。

例えば、以下のような例を考えてみます。

  • IDが2番のブログから、公開されているブログ記事を読み込みます。
  • ベースネームが「price」という整数型のカスタムフィールドの値が、1000以上2000以下になっているという条件を指定します。
  • ベースネームが「weight」という整数型のカスタムフィールドの値が、500以上1000以下になっているという条件を指定します。
  • priceカスタムフィールドの昇順でブログ記事を並べ替えます。
  • priceカスタムフィールドの値が同じブログ記事が複数ある場合は、それらをweightカスタムフィールドの項順で並べ替えます。

この場合、カスタムフィールドの情報があるテーブル(mt_entry_meta)を2回結合し、それぞれでprice/weightカスタムフィールドの結合/検索条件を指定します。
結合と検索条件を指定する部分のプログラムを書くと、以下のようになります。

$extras['join'] = array(
    'mt_entry_meta m1' => array(
        'condition' => 'm1.entry_meta_entry_id = entry_id'
    ),
    'mt_entry_meta m2' => array(
        'condition' => 'm2.entry_meta_entry_id = entry_id'
    )
);
$where = <<< HERE
entry_blog_id = 2
and entry_status = 2
and m1.entry_meta_type = 'field.price'
and m1.entry_meta_vinteger_idx between 1000 and 2000
and m2.entry_meta_type = 'field.weight'
and m2.entry_meta_vinteger_idx between 500 and 1000
order by m1.entry_meta_vinteger_idx, m2.entry_meta_vinteger_idx desc
HERE;
require_once('lib/class.mt_entry.php');
$_entry = new Entry;
$entries = $_entry->Find($where, false, false, $extras);

まず、2~4行目と5~7行目で、ブログ記事のテーブルにカスタムフィールドのテーブルを2回結合しています。
テーブル名を指定する部分を「mt_entry_meta m1」「mt_entry_meta m2」と書いていて、それぞれに「m1」「m2」の別名を指定しています。

12~13行目では、priceカスタムフィールドの値が1000以上2000以下という条件を指定しています。
1回目の結合でテーブルにm1という別名を付けましたので、条件の中でフィールドを指定する箇所を「mt.entry_meta_type」のように書いて、別名を指定しています。

14~15行目では、12~13行目と同じ考え方で、weightカスタムフィールドの値が500以上1000以下という条件を指定しています。

そして、16行目で並べ替えの条件を指定しています。
ここでも、フィールド名の前に「m1.」「m2.」の別名を指定します。