使用圖查詢遍歷關係

已完成

小提示

有關更多詳細信息,請參閱 文本和圖像 選項卡!

部分資料關係自然以網絡形式呈現,包括社交連結、組織階層、產品推薦及詐欺偵測模式。 雖然你可以用外鍵和連接來建模這些關係,但使用 MATCH 運算子進行圖查詢,提供了一種更直覺且通常更有效率的方式來遍歷連接資料。

視覺化圖形資料結構

在撰寫圖查詢前,先視覺化圖資料的組織方式會有所幫助。 想像一個簡單的社交網路,大家彼此認識並購買產品:

這是一個圖形資料模型的示意圖,展示「人員」與「產品」節點,並透過「認識」與「購買」關係邊相互連接。

在此模型中:

  • 節點 (方框)代表像人和產品這樣的實體
  • 邊 (箭頭)代表節點間的關係。 箭頭方向表示關係方向(愛麗絲認識鮑勃,不一定是鮑勃認識愛麗絲)。

備註

此圖說明了圖形的概念。 本單元的程式碼範例使用類似但簡化的資料,聚焦於特定特徵。

了解圖形功能

圖功能擴展了關聯模型,加入專用的節點與邊緣資料表。 節點代表實體,如人員、產品和地點。 邊表示節點之間的關係,例如「認識」、「購買」或「位於」。

圖查詢的主要優勢是模式匹配。 你不必寫複雜的多路連接,而是用 ASCII 風格的語法表達你想要的模式:

-- Traditional relational approach (multiple joins)
SELECT p1.Name, p2.Name
FROM Person AS p1
INNER JOIN Friendship AS f ON p1.PersonID = f.Person1ID
INNER JOIN Person AS p2 ON f.Person2ID = p2.PersonID;

-- Graph approach (pattern matching)
SELECT Person1.Name, Person2.Name
FROM Person AS Person1, Friendship, Person AS Person2
WHERE MATCH(Person1-(Friendship)->Person2);

備註

圖表與現有的關聯功能完全相容。 你可以將圖表與一般資料表結合,使用索引,並套用所有標準的 T-SQL 操作。

建立節點資料表

節點表會在你的圖中儲存實體。 使用CREATE TABLE及AS NODE子句建立它們:

-- Create a Person node table
CREATE TABLE dbo.Person (
    PersonID INT PRIMARY KEY,
    Name NVARCHAR(100) NOT NULL,
    Email NVARCHAR(200),
    Department NVARCHAR(50)
) AS NODE;

-- Create a Product node table
CREATE TABLE dbo.Product (
    ProductID INT PRIMARY KEY,
    Name NVARCHAR(200) NOT NULL,
    Category NVARCHAR(100),
    Price DECIMAL(10, 2)
) AS NODE;

-- Create a Location node table
CREATE TABLE dbo.Location (
    LocationID INT PRIMARY KEY,
    City NVARCHAR(100) NOT NULL,
    CountryRegion NVARCHAR(100) NOT NULL
) AS NODE;

SQL Server 會自動在節點資料表中新增一 $node_id 欄,唯一識別每個節點。 系統內部使用此欄位來建立圖的關係。

以下範例會在「人員」節點資料表中插入四筆人員資料,接著查詢該資料表,以顯示與業務相關的欄位,以及系統自動產生的 $node_id。 請注意,INSERT 陳述式僅使用使用者定義的欄位。 SQL Server 會自動為每一列產生 $node_id。

-- Insert person data using standard INSERT syntax
INSERT INTO dbo.Person (PersonID, Name, Email, Department)
VALUES 
    (1, 'Alice Johnson', 'alice@contoso.com', 'Engineering'),
    (2, 'Bob Smith', 'bob@contoso.com', 'Marketing'),
    (3, 'Carol Davis', 'carol@contoso.com', 'Engineering'),
    (4, 'David Lee', 'david@contoso.com', 'Sales');

-- Query shows the system-generated $node_id alongside user columns
SELECT $node_id, PersonID, Name FROM dbo.Person;

建立邊緣表格

邊緣表代表節點間的關係。 使用CREATE TABLE及AS EDGE子句建立它們:

-- Create a "reports to" relationship edge
CREATE TABLE dbo.ReportsTo (
    StartDate DATE,
    ReportType NVARCHAR(50)
) AS EDGE;

-- Create a "purchased" relationship edge
CREATE TABLE dbo.Purchased (
    PurchaseDate DATE NOT NULL,
    Quantity INT NOT NULL,
    TotalAmount DECIMAL(10, 2)
) AS EDGE;

-- Create a "knows" relationship edge (social connection)
CREATE TABLE dbo.Knows (
    ConnectionDate DATE,
    ConnectionStrength INT  -- 1-10 scale
) AS EDGE;

SQL Server 會自動將 $edge_id、$from_id 和 $to_id 欄位加入邊緣資料表。 你可以透過指定連接節點的 $from_id 值和 $to_id 值來插入邊,就像這樣:

-- Alice reports to Bob
INSERT INTO dbo.ReportsTo ($from_id, $to_id, StartDate, ReportType)
SELECT 
    (SELECT $node_id FROM dbo.Person WHERE Name = 'Alice Johnson'),
    (SELECT $node_id FROM dbo.Person WHERE Name = 'Bob Smith'),
    '2023-01-15',
    'Direct';

-- Create social connections
INSERT INTO dbo.Knows ($from_id, $to_id, ConnectionDate, ConnectionStrength)
SELECT 
    (SELECT $node_id FROM dbo.Person WHERE Name = 'Alice Johnson'),
    (SELECT $node_id FROM dbo.Person WHERE Name = 'Carol Davis'),
    '2022-06-01',
    8;

小提示

邊緣表可以儲存關於該關係本身的屬性,例如日期、權重或類型。 這對於時間分析或加權圖演算法非常有用。

使用 MATCH 子句查詢圖

這個 MATCH 子句使用一種模式語法來指定你想找到的關係。 基本模式使用箭頭來表示關係方向:

-- Find who reports to whom
SELECT 
    Employee.Name AS Employee,
    Manager.Name AS Manager,
    r.StartDate
FROM dbo.Person AS Employee, 
     dbo.ReportsTo AS r, 
     dbo.Person AS Manager
WHERE MATCH(Employee-(r)->Manager);

箭頭方向很重要:

  • (Node1)-(Edge)->(Node2):邊從節點 1 到節點 2
  • (Node1)<-(Edge)-(Node2):邊從節點 2 到節點 1

以下範例列出所有認識愛麗絲的人:

SELECT 
    Connector.Name AS PersonWhoKnowsAlice,
    k.ConnectionStrength
FROM dbo.Person AS Connector, 
     dbo.Knows AS k, 
     dbo.Person AS Target
WHERE MATCH(Connector-(k)->Target)
  AND Target.Name = 'Alice Johnson';

穿越多重關係

單跳查詢能找到直接連結,但圖資料庫在多跳遍歷上表現優異。 你可以在一個 MATCH 子句中串接多個邊緣模式,追蹤多個關係的路徑。 此功能讓您能回答「我朋友的朋友是誰?」或「我的同事買了什麼產品?」等問題,而不必寫出複雜的巢狀子查詢。

以下範例是透過鏈結兩個認識關係來找到朋友的朋友。 模式 Person1-(k1)->Person2-(k2)->Person3 從 Person1 開始,沿著一條 KNOWS 邊到 Person2,再沿著另一條 KNOWS 邊到達 Person3:

-- Find friends of friends (2-hop connections)
SELECT DISTINCT
    Person1.Name AS Person,
    Person3.Name AS FriendOfFriend
FROM dbo.Person AS Person1,
     dbo.Knows AS k1,
     dbo.Person AS Person2,
     dbo.Knows AS k2,
     dbo.Person AS Person3
WHERE MATCH(Person1-(k1)->Person2-(k2)->Person3)
  AND Person1.Name = 'Alice Johnson'
  AND Person3.Name <> Person1.Name;  -- Exclude self

你也可以在單次遍歷中結合不同類型的關係。 以下範例將從 KNOWS 跨越到 PURCHASED 邊,找出某人認識的人購買過哪些產品:

-- Find products purchased by people in the same department
SELECT DISTINCT
    p1.Name AS Person,
    p1.Department,
    prod.Name AS Product
FROM dbo.Person AS p1,
     dbo.Knows AS k,
     dbo.Person AS p2,
     dbo.Purchased AS pu,
     dbo.Product AS prod
WHERE MATCH(p1-(k)->p2-(pu)->prod)
  AND p1.Department = p2.Department;

這很重要

每個邊表別名只能在同一圖案中 MATCH 出現一次。 若要多次遍歷相同的邊型,請使用不同的別名。

使用SHORTEST_PATH進行可變長度遍歷

你可以用來 SHORTEST_PATH 尋找跨越不同數量關係的最短連結。 FOR PATH關鍵字標示參與變長匹配的表格,量詞如+(一個或多個)或{1,3}(一至三個)控制遍歷深度。

以下範例找出所有在三跳範圍內可從愛麗絲到達的人,並計算他們與愛麗絲的距離:

SELECT 
    StartPerson.Name,
    LAST_VALUE(ReachablePerson.Name) WITHIN GROUP (GRAPH PATH) AS ReachablePerson,
    COUNT(ReachablePerson.Name) WITHIN GROUP (GRAPH PATH) AS Distance
FROM dbo.Person AS StartPerson,
     dbo.Knows FOR PATH AS k,
     dbo.Person FOR PATH AS ReachablePerson
WHERE MATCH(SHORTEST_PATH(StartPerson(-(k)->ReachablePerson){1,3}))
  AND StartPerson.Name = 'Alice Johnson';

在圖與關聯式方法間選擇

圖查詢不一定是最佳選擇。 在決定圖形與傳統關係方法時,請參考以下指引:

在以下情況下使用圖查詢:

  • 關係是你查詢的主要焦點
  • 您需要遍歷可變或未知的深度 (朋友的朋友)
  • 資料自然形成一個網絡(社交圖譜、階層結構、路由)
  • 查詢模式在關聯式 SQL 中需要多次自連結
  • 你正在進行路徑尋找或連通性分析

當以下情況使用關聯性查詢:

  • 關係簡單且深度固定(父子關係,只有一層)
  • 你主要是在過濾和彙整實體屬性
  • 資料模型大多為表格形式,關聯性較少
  • 效能至關重要,在外鍵上建立的索引即可滿足需求。
  • 你的團隊對傳統 SQL 模式比較熟悉

疑難排解常見的圖表查詢挑戰

圖查詢有獨特的語法要求,可能會造成錯誤。 下表說明常見挑戰及解決方法。

挑戰 原因 解決方法
查詢未回傳結果 圖案中的 MATCH 箭頭方向與邊緣插入方式不符 確認邊緣是怎麼插入的。 如果 $from_id 是員工且 $to_id 是經理,箭頭必須從員工指向經理。
帶有重複邊的語法錯誤 在同一個 MATCH 模式中重複使用了相同的邊別名 對同一邊類型的每次遍歷使用不同的別名。
SHORTEST_PATH 查詢失敗 邊緣和節點表格未標記為 FOR PATH 將 FOR PATH 關鍵字添加到所有參與可變長度匹配的表格。
邊參考不存在的節點 使用業務關鍵欄位代替 $node_id 值 插入邊時,請使用子查詢從節點表中選擇 $node_id 。

備註

圖形表與 MATCH 運算子可在 SQL Server 2017 及以後版本,以及 Azure SQL 資料庫中使用。 此 SHORTEST_PATH 函式需要 SQL Server 2019 或更新版本。 請查看你平台的文件以了解具體功能可用性。

欲了解更多圖功能資訊,請參閱 SQL Server 的圖處理 及 MATCH (Transact-SQL)。