フィルター処理を行うと、重要な行に結果が絞り込まれます。 集計では、これらの行がカウント、合計、および平均にまとめられます。 この記事では、Microsoft Fabricのグラフに対して GQL クエリで両方の手法を適用する方法について説明します。
この例では、 ソーシャル ネットワークのサンプル データセットを使用します。 クエリフローと文のエンドツーエンドの説明については、 GQL言語ガイドをご覧ください。
この記事は、行やパターンのフィルタリング、グループ化・非グループ化の集約、集約特有のフィルター、条件付きルーティングに使用してください。 マルチホップパターンの構築やパスの選択については、「 グラフパターンクエリを書きます」を参照してください。 すぐに適応できるビジネスタスクについては、「 一般的なGQLクエリを書く」を参照してください。
前提条件
- ソーシャルネットワークのサンプルデータセットから作成されたグラフ項目で、ノードタイプ、エッジタイプ、プロパティはソーシャルネットワークスキーマの例で説明されています。
- 基本的な
MATCHとRETURNクエリに関する知識。 GQL 言語ガイドを参照してください。
FILTER を使用して行をフィルター処理する
FILTERを使用して、条件を満たす行のみを保持します。
FILTERの後にMATCHを配置して、一致した結果を絞り込みます。
次のクエリは、名前と誕生日を持つすべての女性を返します。
MATCH (p:Person)
FILTER p.gender = 'female'
RETURN p.firstName, p.lastName, p.birthday
複数の条件を AND と ORと組み合わせます。 たとえば、次のクエリは、1990 年より前に生まれたすべての女性の名前を返します。
MATCH (p:Person)
FILTER p.gender = 'female' AND p.birthday < 19900101
RETURN p.firstName, p.lastName
ヒント
どのノードや辺がマッチに参加できるかを条件に定義する場合は、インラインの WHERE 節を用いましょう。 条件が前の文で生成された行に適用される場合に FILTER を用いましょう。 述語配置は最短経路の結果を変えることがあります。詳細は 「経路選択の前後に述語を置く」を参照してください。
パターンマッチング中のフィルター処理
MATCHパターン内のインライン WHERE 節は、どのノードやエッジがマッチに該当するかを制限します。 クエリオプティマイザーはスキャン中に同等の述語を適用できるため、インライン構文は別 FILTERより本質的に高速ではありません。 意図された意味を表現する形式を選びましょう。
たとえば、1994 年より前に生まれた人を会社と共に見つけるには、名前が "A" で始まる企業に結果を制限します。
MATCH (p:Person WHERE p.birthday < 19940101)-[:workAt]->(c:Company WHERE c.name STARTS WITH 'A')
RETURN p.firstName, p.lastName, c.name
エッジ プロパティも同様にフィルタリングします。 たとえば、2000 年以降に会社で働き始めた人のみを返すには、次のようにします。
MATCH (p:Person)-[w:workAt WHERE w.workFrom >= 2000]->(c:Company)
RETURN p.firstName, p.lastName, c.name, w.workFrom
インラインフィルタリングとマッチ後フィルタリングの選択についての詳細は、「 Optimal GQL query performance」をご覧ください。
フィルターで null 値を処理する
GQL では、3 つの値を持つロジックが使用されます。述語は、 TRUE、 FALSE、または UNKNOWNに評価されます。 プロパティ値が null の場合、比較は UNKNOWNを返します。
FILTER では、 UNKNOWN が一致しないものとして扱われるので、行は除外されます。
IS NULLとIS NOT NULLを使用して、null 値を明示的にテストします。
-- Only include people whose browser is known
MATCH (p:Person)
FILTER p.browserUsed IS NOT NULL
RETURN p.firstName, p.browserUsed
プロパティが null の場合は、 coalesce() を使用して既定値に置き換える:
MATCH (p:Person)
RETURN p.firstName, coalesce(p.browserUsed, 'Unknown browser') AS browser
Caution
NULL = NULLは、UNKNOWNではなく、TRUEに評価されます。 常にIS NULLを使用して、等価性ではなく null 値をテストします。
RETURN を使用して結果を集計する
RETURNの集計関数を使用して、結果を集計します。 グラフは以下の集計関数をサポートしています: COUNT、 SUM、 AVG、 MIN、 MAX、 COLLECT_LIST、 COLLECT_ONE、 COLLECT_ELEMENTS。
たとえば、グラフ内のすべてのユーザーをカウントするには、次のようにします。
MATCH (p:Person)
RETURN count(*) AS totalPeople
従業員を雇用する個別の企業の数など、個別の値をカウントするには:
MATCH (p:Person)-[:workAt]->(c:Company)
RETURN count(DISTINCT c) AS companyCount
1つのアグリゲートに対するフィルタ入力
集計の後に FILTER (WHERE predicate) を加えて、その集計の入力のみをフィルタリングします。 同じ RETURN 内の他の集体は依然としてすべての入力行を受け取ります。
MATCH (p:Person)
RETURN count(*) AS allPeople,
count(*) FILTER (WHERE p.birthday < 19900101) AS peopleBornBefore1990
集計フィルター内に LIMIT を追加して、条件を満たす行を最大でその数まで使用します。 クエリはアグリゲート固有の限界の前に述語を適用します。
MATCH (p:Person)
RETURN count(*) FILTER (WHERE p.birthday < 19900101 LIMIT 100) AS sampleCount
集計固有の FILTER と LIMIT はクエリの他の行を削除しません。 行ストリームをフィルタリングしたいときは、 FILTER 文やマッチレベル WHERE 節を使いましょう。
値を収集する
COLLECT_LISTを使って、null 値を含み、各入力値に対して1つのリスト要素を返します。 重複を削除するには、DISTINCT を追加してください。
MATCH (p:Person)
RETURN collect_list(DISTINCT p.browserUsed) AS browsers
COLLECT_ONE はnullでない入力値を1つ返します。 選択された値は決定論的ではないので、グループのどの値をも許容できる場合にのみ使用してください。
COLLECT_ELEMENTS リスト値入力を受け付け、それらの要素を1つのリストに連結します:
MATCH (p:Person)
RETURN collect_elements([p.firstName, p.lastName]) AS names
列をグループ化しない場合、入力行のない集約クエリはCOLLECT_LISTから空のリスト、COLLECT_ONEからはCOLLECT_ELEMENTSとnullを返します。
GROUP BY を使用して結果をグループ化する
GROUP BYのRETURNを使用して、共有値で行をグループ化し、各グループ内の集計を計算します。 このグループ化は、SQL GROUP BYと同等の GQL です。
たとえば、会社ごとの従業員数をカウントするには、次のようにします。
MATCH (p:Person)-[:workAt]->(c:Company)
LET companyId = c.id, companyName = c.name
RETURN companyId, companyName, count(*) AS employeeCount
GROUP BY companyId, companyName
ORDER BY employeeCount DESC
複数の列でグループ化し、一度に複数の集計を計算します。 たとえば、性別とブラウザーで人物数と誕生日の範囲を分割し、最も一般的な 10 個の組み合わせを返します。
MATCH (p:Person)
LET gender = p.gender
LET browser = p.browserUsed
RETURN gender,
browser,
count(*) AS personCount,
min(p.birthday) AS earliestBirthday,
max(p.birthday) AS latestBirthday
GROUP BY gender, browser
ORDER BY personCount DESC
LIMIT 10
Note
RETURN内のすべての非集計式は、GROUP BYに含める必要があります。
GROUP BYに含まれていない式では、集計関数を使用する必要があります。
集計結果の並べ替えと制限
ORDER BYとLIMITをGROUP BYと共に使用して、top-N の結果を見つけます。
たとえば、上位 5 都市を住民数別に検索するには、次のようにします。
MATCH (p:Person)-[:isLocatedIn]->(city:City)
LET cityId = city.id, cityName = city.name
RETURN cityId, cityName, count(*) AS residentCount
GROUP BY cityId, cityName
ORDER BY residentCount DESC
LIMIT 5
Important
ORDER BYの前にLIMITを配置します。
LIMIT は常に、既に並べ替えられた結果セットに適用されます。
条件付きステートメントを使用して行をルーティングする
条件文を使って、各入行を最初の一致する分岐にルーティングします。 入力は集約だけでなく、以前のクエリ段階からも得られます。 例えば、以下のクエリは従業員数を計算した後に企業を分類します:
MATCH (p:Person)-[:workAt]->(c:Company)
LET companyId = c.id, companyName = c.name
RETURN companyId, companyName, count(*) AS employeeCount
GROUP BY companyId, companyName
NEXT
WHEN employeeCount >= 100u THEN
RETURN companyId, companyName, employeeCount, 'Large' AS category
WHEN employeeCount >= 10u THEN
RETURN companyId, companyName, employeeCount, 'Medium' AS category
ELSE
RETURN companyId, companyName, employeeCount, 'Small' AS category
ブランチは、式を返すだけでなく、完全なクエリ文やネストされた手続きを実行することができます。 以下の例では、3行の入力行を異なる分岐形状に通します。 一方の分岐は MATCHを実行し、もう一方は UNION ALL と2つの集約を組み合わせて結果を集約し、フォールバック分岐は定数を返します:
FOR selector IN [1, 2, 3]
RETURN selector
NEXT
WHEN selector = 1 THEN
MATCH (:Person)-[:knows]->(:Person)
RETURN count(*) AS total, 'Knows edges' AS category
WHEN selector = 2 THEN {
MATCH (:Person)-[:workAt]->(:Company)
RETURN count(*) AS partialCount
UNION ALL
MATCH (:Person)-[:studyAt]->(:University)
RETURN count(*) AS partialCount
NEXT
RETURN sum(partialCount) AS total, 'Affiliation edges' AS category
}
ELSE
RETURN 0u AS total, 'No selected metric' AS category
クエリエンジンは各行の述語を順番に評価します。 最初に一致したブランチのみを実行します。 述語が UNKNOWNに評価された場合、評価は次の枝で続きます。
ELSEがない場合、WHEN枝と一致しない行は省略されます。
条件文は CASE 式とは異なります。 グラフは等号に基づく値選択のための単純な CASE <expression> WHEN <value> 式をサポートしています。 検索済み CASE WHEN <predicate> 表現はサポートされていません。 詳細については、 条件文を参照してください。