バインド変数と集計関数を使用する
学習の目的
この単元を完了すると、次のことができるようになります。
- Apex バインド変数を挿入してクエリを動的にする。
- 集計関数を使用して、クエリのデータを積み上げ集計する。
- クエリ結果にグルーピングを適用する。
- WHERE 句を使用する状況と HAVING 句を使用する状況を識別する。
一緒にトレイルを進みましょう
エキスパートの説明を見ながらこのステップを実行したい場合は、次の動画をご覧ください。これは Trailhead Live の「Trail Together」(一緒にトレイル) シリーズの一部です。
(巻き戻して最初から見直したい場合、このクリップは 1:10:42 分から開始されます。)
はじめに
これまでに、基本的な SOQL クエリを記述する方法と、親オブジェクトまたは子オブジェクトの項目を含むクエリを作成する方法を説明しました。けれども、ご存知のとおり、アプリケーションの開発はそれぞれ異なります。そのため、特定の問題を解決するためにビジネスロジックを調整する方法を心得ていることが大切です。
バインド変数
コードを調整する 1 つの手法がバインド変数を使用することです。ユーザーインターフェースでフォームを開き、特定の結果を検索するために入力項目を変更する場合に似ています。では、DreamHouse アプリケーションの例を見てみましょう。住宅を販売する不動産仲介業者が、$200,000 未満の物件にどのようなものがあるか確認しようとしているとします。そこで以下のクエリを記述します。
List<Property__c> property = [SELECT Id, Name, Price__c FROM Property__c WHERE Price__c < 200000];
システム管理者にとっては、難しいものではありません。けれども、このクエリは静的で、常に $200,000 未満の住宅を返します。他の仲介業者や住宅購入希望者が開発者コンソールで SOQL クエリを記述して実行できない場合はどうなるでしょうか? こうした人々が、各自の希望する価格で住宅を簡単に絞り込める手段が必要です。予算が $200,000 の購入者にも、$800,000 の購入者にも対応するクエリを作成するにはどうすればよいでしょうか? ここで登場するのがバインド変数です。バインド変数は、SOQL クエリで使用する Apex 変数です。後から指定する特定の値のプレースホルダーとしてバインド変数を使用します。
maxHomeValue というバインド変数について考えてみましょう。Apex でこの変数を宣言し、クエリで次のとおり使用します。
Integer maxHomeValue = 200000; List<Property__c> property = [SELECT Name, Price__c FROM Property__c WHERE Price__c < :maxHomeValue];
クエリでは、バインド変数の前にコロン (:
) が付けられます。このクエリで Property (物件) オブジェクトの名前と価格が返されます。ただし、WHERE Price__c < :maxHomeValue
により、住宅の価格を基準に結果が絞り込まれます。maxHomeValue
バインド変数の値は、クエリの外側に設定されます。実際の例を見てみましょう。
- Trailhead Playground で、 をクリックして、[Search (検索)] ボックスに
Dream
と入力し、[DreamHouse] アプリケーションを選択します。
-
[Property Explorer] をクリックします。
Property Explorer を使用すると、最大価格帯など、多くの検索条件に基づいて使用可能なプロパティが検索されます。[最高価格] スライダーでは maxHomeValue バインド変数の値を受け入れます。
- [最高価格] スライダーを [550K] に動かします。
スライダーを動かすたびに、バインド変数によってコードの関連付けられた値が変化します。クエリが実行され、[Property Explorer] ページに表示される物件リストに結果が追加されます。
WHERE
句にバインド変数を使用すれば、クエリを実行する前にコードに可変変数を設定できます。つまり、バインド変数によってクエリが動的になります。ユーザーごとにクエリをカスタマイズするには、ユーザー入力に基づいてバインド変数の値を設定します。今後コードを変更して確認していくうちに、さまざまな種別の項目のデータが頻繁に変更されることに気付くものと思われます。
集計関数
レポートでは積み上げ集計項目を使用して、関連レコードの値を計算します。たとえば、物件の合計数や、市内の物件の平均値または最高値を計算したいと思うことがあります。SOQL では、上記をはじめとする計算に集計関数を使用します。
SOQL クエリの集計関数
集計関数 |
説明 |
例 |
---|---|---|
COUNT() |
項目に関連付けられている行数を返します。 |
SELECT COUNT(Name)FROM Broker__c |
COUNT_DISTINCT() |
クエリ条件に一致する行数 (重複を除く) を返します。 |
SELECT COUNT_DISTINCT(City__c)FROM Property__c |
MIN() |
項目の最小値を返します。 |
SELECT MIN(Days_On_Market__c)FROM Property__c |
MAX() |
項目の最大値を返します。 |
SELECT MAX(Beds__c)FROM Property__c |
AVG() |
数値項目の平均値を返します。 |
SELECT City__c, AVG(Days_On_Market__c)FROM Property__c GROUP BY City__c |
SUM() |
数値項目の合計値を返します。 |
SELECT SUM(Price__c), Broker__r.Name FROM Property__c GROUP BY Broker__r.Name |
では、都市にある物件を例に説明していきます。このシンプルなクエリからはじめましょう。
SELECT City__c FROM Property__c
このクエリで、12 の各物件の都市が返されます。
都市の完全リストが必要なわけではないため、クエリを変更して集計関数を使用します。物件の合計数を取得するには、COUNT() 関数を使用します。
集計関数は、クエリの SELECT 句に次のとおり配置されます。
関数名に続く括弧に、計算に使用する項目の名前を挿入します。この例では、City__c 項目の値を数えます。
COUNT() クエリを実行する
- クエリエディターで、次のとおり入力します。
SELECT City__c FROM Property__c
-
[Execute (実行)] をクリックします。
クエリ結果の 12 行に各物件の都市が示されます。
- クエリを編集して、次のとおり City__c 項目が COUNT() 関数に挿入されるようにします。
SELECT COUNT(City__c) FROM Property__c
-
[Execute (実行)] をクリックします。
このクエリ結果は、City__c 項目に基づく物件数の 12 になります。
12 の物件が 2 つの都市に存在するのであれば、なぜ件数が 2 でなく、12 になるのかと疑問に思うかもしれません。この理由は、COUNT() 関数がすべての値を数えるためで、多くの場合、同じ値の複数のレコードがそれぞれ数えられます。
たとえば、1 人のブローカーが 1 つの都市のすべての物件を担当するとします。ブローカーは何人必要でしょうか? 別の言い方をすると、12 の物件がいくつの都市に存在しているでしょうか? 都市の実数を数える場合は、別の関数が必要です。(述べ数でなく、重複を除いた実数が必要で、「unique」や「distinct」で表します。)
COUNT_DISTINCT() は COUNT() とほぼ同じですが、(重複を除いた) 実数を返す点が異なります。
COUNT_DISTINCT クエリを実行する
- クエリエディターで、クエリを編集し、次のような COUNT_DISTINCT() 関数を使用します。
SELECT COUNT_DISTINCT(City__c) FROM Property__c
-
[Execute (実行)] をクリックします。
この結果は、全物件の City__c 値の実数である 2 になるはずです。
City__c 項目に表示されている値は Cambridge、Boston、Brookline のみです。COUNT() 関数と COUNT_DISTINCT() 関数は大文字と小文字を区別します。つまり、Cambridge と cambridge は重複ではなく、2 つの一意の値とみなされます。
MIN()、MAX()、AVG()、SUM()
その他の有用な集計関数に、MIN()、MAX()、AVG()、SUM() が挙げられます。
MIN() 関数と MAX() 関数は見てのとおりです。MIN() は最小 (最低) の値を見つけ、MAX() は最大 (最高) の値を見つけます。この 2 つの関数の特異な点は、数字のほかに日時も処理できることです。
- クエリエディターで、次のとおり入力します。
SELECT MIN(Date_Listed__c) FROM Property__c
-
[Execute (実行)] をクリックします。
MIN() 関数では一番古い日付が返されます。MAX() 関数では最新の日付が返されます。
MIN() 関数と MAX() 関数は選択リスト値の並び替え順も認識するため、選択リストの最初の値と最後の値を見つけることができます。
AVG() 関数はすべての値の平均を計算します。SUM() 関数はすべての値の合計を計算します。どちらの関数も計算を実行するものであるため、数値を含む項目でのみ機能します。
集計関数の結果を分類する
集計データに基づいて値を計算した後、サマリーレポートの場合と同様に、結果を分類して報告したいと考えることがあります。SOQL クエリの値を分類するには、GROUP BY 句を使用します。たとえば、DreamHouse Realty のお客様が、物件を販売 (完了) した経験があるブローカーを探しているとします。
GROUP BY を実際に使ってみる
次に、クエリで GROUP BY 句を使用します。
- クエリエディターで、次のとおり入力します。
SELECT MAX(Status__c), Broker__r.Name FROM Property__c GROUP BY Broker__r.Name
-
[Execute (実行)] をクリックします。
8 行の結果が示されます。
このクエリでは物件がブローカー別に分類されます。各ブローカーの物件の Status__c 値のうち、最も進行した状況がリストされます。つまり、[状況] 選択リストの値のうち、選択リストの最終値に最も近いものです。ここで知りたいのは物件を販売した経験があるブローカーであるため、この結果をさらに絞り込みます。先ほどのクエリに戻りましょう。
集計関数の結果を絞り込む
結果を絞り込むもう 1 つの方法は HAVING 句を使うことです。HAVING 句は、集計関数によって返された結果を絞り込みます。
物件を販売したことがあるブローカーを見つけることができそうです。前のクエリでは、状況に関係なく、物件を担当しているブローカーのリストが返されました。HAVING 句を使用して、上記の結果を絞り込んでみましょう。
- クエリエディターで、次のとおり入力します。
SELECT MAX(Status__c), Broker__r.Name FROM Property__c GROUP BY Broker__r.Name HAVING MAX(Status__c) = 'Closed'
-
[Query (クエリ)] をクリックします。1 人のブローカーを取得します。
欲しかったのはこのリストです! HAVING 句の使用により、状況が [完了] の物件に絞り込まれました。
WHERE 句と HAVING 句はよく似ています。WHERE を使用すべきか、HAVING を使用すべきかは次の点で判断します。
- WHERE 句は、集計関数がない SOQL クエリのレコードを絞り込みます。
- HAVING 句は、集計関数でデータが集計された後の結果を絞り込みます。
このモジュールで学習したとおり、SOQL は Salesforce 組織のデータにアクセスするための優れたツールです。Apex のコーディングスキルを伸ばし、広げていく中で、SOQL の知識を活用する多くの機会に遭遇するものと思われます。そのような機会が訪れた場合には、このモジュールに記載のリソースで Apex や SOQL の詳細や例を確認できることを覚えておいてください。では、早速 SOQL を使用してクエリを実行してみてください。
リソース
-
Salesforce 開発者ドキュメント: SOQL クエリおよび SOSL クエリでの Apex 変数の使用
-
Salesforce 開発者ドキュメント: 集計関数
-
Salesforce 開発者ドキュメント: SOQL SELECT の例
-
Salesforce 開発者ドキュメント: GROUP BY