標準オブジェクトでリレーションクエリを作成する
学習の目的
この単元を完了すると、次のことができるようになります。
- 2 種類のリレーションクエリについて説明する。
- 2 つのオブジェクト間のリレーションを特定する。
- ドット表記を使用して子-親クエリを作成する。
- サブクエリを使用して親-子クエリを作成する。
- サブクエリを使用してクエリ結果を絞り込む。
Trail Together の動画
エキスパートの説明を見ながらこのステップを実行したい場合は、Trailhead Live の Trail Together シリーズの一部である、こちらの動画をご覧ください。
(巻き戻して最初から見直したい場合、このクリップは 36:18 分から開始されます。)
リレーションクエリについて
Salesforce システム管理者であれば、関連レコードからデータを取り込む数式項目のことをすでにご存知と思います。ここではオブジェクトリレーションに関する各自の知識を SOQL クエリの記述に適用します。
FROM 句 は 1 つのオブジェクトに限定されますが、リレーションクエリを使用すれば 2 つの関連オブジェクトにアクセスできます。リレーションクエリでは、2 つの異なるオブジェクト間のリレーションを利用して両方のオブジェクトの項目を返します。クロスオブジェクトクエリのようなものと考えることができます。
たとえば、次の要件があるとします。
「すべての取引先責任者と、各取引先責任者の取引先名を取得する。」
取引先責任者オブジェクトにクエリを実行できますが、このオブジェクトに [取引先名] 項目はありません。取引先名は、取引先責任者に関連する取引先にある [名前] 項目です。組織では、数式項目を使用して任意の関連オブジェクトの項目にアクセスします。Apex では、リレーションクエリを使用しますが、2 つのオブジェクトがどのように関連しているかによってリレーションクエリの種別が異なります。
取得するレコードと使用するクエリ:
- 子オブジェクトのレコードを取得し、関連する親オブジェクトの項目を含める場合は、子-親クエリを使用します。
- 親オブジェクトのレコードを取得し、関連する子オブジェクトの項目を含める場合は、親-子クエリを使用します。
使用するクエリの種別を判断する前に、2 つのオブジェクト (取引先責任者と取引先) がどのように関連しているかを知る必要があります。つまり、どちらが親で、どちらが子かを確認します。
オブジェクトのリレーションを特定する
システム管理者であれば、組織の主従関係についてもご存知かと思います。主従関係は親-子リレーションです。主オブジェクトが親で、従オブジェクトが子になります。クエリに含める 2 つのオブジェクトに主従関係がある場合は、どちらが親で、どちらが子かを確認します。
クエリに含める 2 つのオブジェクトのことをよく知らない場合や両者の関係が不明な場合は、オブジェクトマネージャーでそのオブジェクトについて調べます。まず、子ではないかと思われるオブジェクトの [項目とリレーション] を確認します。次に、親オブジェクトに関係していると思われる項目名を見つけます。
たとえば、取引先責任者には、Lookup(Account) データ型の AccountId 項目があります。前述のとおり、コードで必要なのは項目名 (AccountId) で、項目の表示ラベル (取引先名) ではありません。
AccountId 項目の詳細にある [子リレーション名] は [Contacts] で、複数形です。標準オブジェクトのリレーション名はデフォルトで、子オブジェクト名の複数形です。
[子リレーション名] で、取引先責任者が取引先の子であることが確認できます。また、親-子クエリ (この単元で後述) に必要なリレーション名も表示されています。
子-親クエリを作成する
取引先責任者と取引先が子-親リレーションであることがわかりました。取引先責任者が子で、取引先が親です。すべての取引先責任者 (子) と、各取引先責任者の取引先 (親) 名を返すためには、子-親クエリが必要です。
子-親クエリでは、子オブジェクトにクエリを実行し、次のようなドット表記を使用して親オブジェクトから項目を取得します。
SELECT Name, Account.Name FROM Contact
この SELECT ステートメントは、取引先責任者オブジェクトにクエリを実行します。SELECT 句の Name は取引先責任者の [名前] 項目で、Account.Name
は取引先責任者に関連している取引先の [名前] 項目です。
子-親クエリを実行する
- 開発者コンソールのクエリエディターで、次のとおり入力します。
SELECT Name, Account.Name FROM Contact
- [Execute (実行)] をクリックします。
結果の最初の 6 行が次のようになります。
Query Results - Total Rows: 20 (クエリ結果 - 行合計: 20) |
|
名前 |
Account.Name |
Rose Gonzales |
Edge Communications |
Sean Forbes |
Edge Communications |
Jack Rogers |
Burlington Textiles Corp of America |
Pat Stumuller |
Pyramid Construction Inc. |
Andy Young |
Dickenson plc |
Tim Barr |
Grand Hotels & Resorts Ltd |
2 列目に、取引先責任者の親取引先オブジェクトの取引先名が示されています。
親-子クエリを作成する
次に、親オブジェクトにクエリを実行して、子オブジェクトの項目を取得する方法を見てみましょう。親-子クエリでは、サブクエリを使用して子オブジェクトの項目を取得します。サブクエリとは、括弧で囲んで別のクエリ内にネストする SELECT ステートメントです。
たとえば、次のような要件があるとします。
「取引先ごとに、取引先名と各関連取引先責任者の名前を返す。」
「各関連」と書かれていることから、リレーションクエリが必要であることがわかります。取引先責任者は取引先の子であるため、ここでは子オブジェクトへのサブクエリを伴う親-子リレーションクエリが必要です。
要件の前半の「取引先ごとに、取引先名を返す」が主クエリで、クエリ全体の外枠を形成します。要件の後半の「各関連取引先責任者の名前」がサブクエリで、主クエリ内にネストされた内部クエリです。
まず、主クエリを SELECT Name FROM Account
と定義します。
次にサブクエリを括弧で囲んで (SELECT Name FROM Contact)
と定義します。
さらに、サブクエリを、主クエリの 2 つ目の項目のように配置します。次のとおり、Name の後にカンマを追加してサブクエリを挿入します。
サブクエリ内では、関連オブジェクトの項目名ではなく、子リレーション名を使用します。そのため、最後のステップとして、次のとおり、サブクエリのオブジェクト名 Contact
を、子リレーション名 Contacts
に変更します。
このクエリで、取引先名と、すべての取引先のすべての取引先責任者名が返されます。詳しく見ていきましょう。
このクエリは 3 段階で実行されます。
- クエリが取引先を 1 つ選択し、その取引先の [名前] 項目を取得します。これが主クエリ (外部クエリ) です。
- 次に、クエリがその取引先の関連取引先責任者を見つけ、各取引先責任者の [名前] 項目を取得します。これがサブクエリ (内部クエリ) です。
- その後、次の取引先に進み、選択したすべての取引先で同じ手順を繰り返します。
親-子クエリを実行する
- クエリエディターで、次のとおり入力します。
SELECT Name, (SELECT Name FROM Contacts) FROM Account
- [Execute (実行)] をクリックします。
結果の最初の 6 行が次のようになります。
Query Results - Total Rows: 12 (クエリ結果 - 行合計: 12) |
|
名前 |
Contacts |
Edge Communications |
[{"Name":"Rose Gonzalez"},{"Name":"Sean Forbes"}] |
Burlington Textiles Corp of America |
[{"Name":"Jack Rogers"}] |
Pyramid Construction Inc. |
[{"Name":"Pat Stumuller"}] |
Dickenson plc |
[{"Name":"Andy Young"}] |
Grand Hotels & Resorts Ltd |
[{"Name":"John Bond"},{"Name":"Tim Barr"}] |
United Oil & Gas Corp. |
[{"Name":"Arthur Song"},{"Name":"Avi Green"},{"Name":"Lauren Boyle"},{"Name":"Stella Pavlova"}] |
これまでとは異なる形式で結果が表示されました。[Query Results (クエリ結果)] ウィンドウに、取引先名と、各取引先に関連付けられている子取引先責任者レコードのコレクションが示されています。「システム管理者のためのオブジェクト指向プログラミング」モジュールで対応付けについて説明したため、この種のコレクションに見覚えがあるのではないでしょうか?
対応付けが何か覚えていなくても心配いりません。ここでおさらいします。対応付けコレクションは、キー - 値ペアをカンマ区切りで示します。キーは項目名 (例: Name) です。キーの後にその値 (例: Jake Llorrac) が続きます。取引先に関連する取引先責任者をクエリする、ネストされた SELECT ステートメントでキー - 値ペアが返されました。
サブクエリで絞り込む
ここで、関連取引先責任者の姓が Forbes である取引先のみが必要であるとします。この厄介な点は、子オブジェクトである取引先責任者の値で、親オブジェクトである取引先を絞り込む必要があることです。主クエリ内にサブクエリをネストしたときと同じ方法で、主クエリの WHERE 句に (子オブジェクトの) サブクエリを使用できます。サブクエリの結果が、主クエリの検索条件のように機能します。クロス条件をご存知の場合、サブクエリに WHERE 句を追加することは、レポートでクロス条件を使用することに相当します。
既存の SELECT Name, (SELECT Name FROM Contacts) FROM Account
クエリを使用します。
次に、姓が Forbes である取引先責任者から AccountId 項目を取得する次のサブクエリが必要です。
(SELECT AccountId FROM Contact WHERE LastName = 'Forbes')
なぜ取引先責任者の AccountId 項目が必要なのかと疑問に思うかもしれません。取引先責任者の AccountId 項目をチェックして、取引先に関連づけられている取引先責任者を見つけるためです。取引先責任者が取引先に関連付けられるのは、取引先責任者オブジェクトの AccountId 項目と取引先オブジェクトの Id 項目の値が同じ場合です (Contact.AccountId = Account.Id
)。そのため、取引先責任者オブジェクトにクエリを実行して、その AccountId 値を返します。取引先責任者に関連付けられている取引先を選択するために、Id 項目にこの値がある取引先を見つけます。
最後に、WHERE 句を主クエリに追加します。ここでは、サブクエリで返された取引先責任者の AccountId 項目に取引先レコードの Id が見つかった場合にのみその取引先を選択します。そのため、次のとおり、WHERE Id IN
の後にサブクエリを追加します。
SELECT Name, (SELECT Name FROM Contacts) FROM Account WHERE Id IN (SELECT AccountId FROM Contact WHERE LastName = 'Forbes')
このクエリは 4 つのことを行います。
- 姓が Forbes の取引先責任者を見つけ、各取引先責任者の AccountId 項目の値を返す。(WHERE 句のサブクエリが実行)
- 次に、取引先の Id 項目を AccountId の値と照合し、一致した場合はその取引先の名前を取得する。(主 WHERE 句が実行)
- 続いて、取引先の関連取引先責任者を見つけ、各取引先責任者の名前を取得する。(主クエリのサブクエリが実行)
- 最後に主クエリが、姓が Forbes である関連取引先責任者がいる各取引先と、該当した取引先ごとに、すべての関連取引先責任者の名前を返す。
条件を設定したクエリを実行する
- クエリエディターで、次のとおり入力します。
SELECT Name, (SELECT Name FROM Contacts) FROM Account WHERE Id IN (SELECT AccountId FROM Contact WHERE LastName = 'Forbes')
- [Execute (実行)] をクリックします。
次のような結果が表示されます。
まとめ
標準オブジェクトに対して適切な種別のリレーションクエリを選択して構築する方法を習得しました。次の単元では、カスタムオブジェクトに対するリレーションクエリについて学習します。