Microsoft Fabric 中的圖形資料過濾與彙整

篩選可以將結果縮小到重要的欄位。 聚合會將這些數據列彙整成計數、總數和平均值。 本文將示範如何在 Microsoft Fabric 中的 GQL 查詢中應用這兩種技術於圖形資料上。

範例中使用社群網路範例資料集。 關於查詢流程與語句的端對端說明,請參閱 GQL 語言指南。

本文可用於列與模式篩選、群組與非群組聚合、聚合特定篩選及條件路由。 關於構建多跳模式及選擇路徑,請參見 撰寫圖模式查詢。 關於即用的商業任務,請參見 撰寫常見的 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

Tip

當條件定義哪個節點或邊可以參與比對時,請使用行內 WHERE 子句。 當條件適用於先前陳述所產生的列時,該條件會被使用 FILTER 。 謂詞的擺放可能會改變最短路徑的結果;參見 「在路徑選擇前或之後放置謂詞」。

模式匹配時的過濾器

WHERE 模式中的內嵌 MATCH 子句會限制哪些節點和邊可符合比對條件。 查詢優化器可以在掃描時套用等效的述詞,因此內嵌語法本質上並不比獨立的 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

欲了解更多關於選擇內嵌過濾與後配對篩選的資訊,請參閱 優化 GQL 查詢效能。

在濾波器中處理空值

GQL 採用三值邏輯:謂詞評估結果為 TRUE、FALSE 或 UNKNOWN。 當屬性值為零時,比較會回傳 UNKNOWN。 FILTER 會 UNKNOWN 被視為不匹配,因此該列被排除。

使用 IS NULL 和 IS NOT NULL 明確測試空值:

-- Only include people whose browser is known
MATCH (p:Person)
FILTER p.browserUsed IS NOT NULL
RETURN p.firstName, p.browserUsed

當屬性可能為空時,請用 coalesce() 替換預設值:

MATCH (p:Person)
RETURN p.firstName, coalesce(p.browserUsed, 'Unknown browser') AS browser

Caution

NULL = NULL 評估為 UNKNOWN,不是 TRUE。 一定要用 IS NULL 來測試空值,而不是等式。

使用 RETURN 取得綜合結果

使用總和函數在RETURN中總結你的結果。 圖支援以下彙總函數:COUNT、、AVGSUM、 COLLECT_ONEMINMAXCOLLECT_LISTCOLLECT_ELEMENTS和 。

例如,計算圖表中的所有人數:

MATCH (p:Person)
RETURN count(*) AS totalPeople

為了計算不同價值,例如有多少家不同公司雇用了員工:

MATCH (p:Person)-[:workAt]->(c:Company)
RETURN count(DISTINCT c) AS companyCount

單一彙總的篩選輸入

在聚合後加 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 值。 新增 DISTINCT 以移除重複內容。

MATCH (p:Person)
RETURN collect_list(DISTINCT p.browserUsed) AS browsers

COLLECT_ONE 回傳一個非空輸入值。 所選值並非確定性,因此只有在群組中任一值都可接受時才使用。

COLLECT_ELEMENTS 接受列表值輸入,並將其元素串接成一個列表:

MATCH (p:Person)
RETURN collect_elements([p.firstName, p.lastName]) AS names

若沒有分組欄位,則在沒有輸入資料列時,彙總查詢會從 COLLECT_ELEMENTS 和 COLLECT_LIST 傳回空清單,並從 COLLECT_ONE 傳回 null。

使用 GROUP BY 來分組結果

使用 GROUP BY 並在 RETURN 中按共享值為資料列分組,然後在每個群組內計算彙總數據。 此群組即為 GQL 中相當於 SQL GROUP BY的 。

例如,計算每家公司員工數:

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 來尋找前N名的結果。

例如,要找到依居民數量排名前五的城市:

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

這很重要

將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

分支可以執行完整的查詢語句和巢狀程序,而不只是回傳表達式。 以下範例會讓三列輸入資料通過不同的分支結構。 其中一個分支執行 MATCH,另一個分支使用 UNION ALL 將兩個彙總結果合併,然後再彙總合併後的結果,而備援分支則回傳一個常數:

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 表達式不同。 Graph 支援用於根據相等性選取值的簡單 CASE <expression> WHEN <value> 運算式。 搜尋表達式 CASE WHEN <predicate> 不受支援。 欲了解更多資訊,請參閱 條件語句。