上一篇簡要介紹了圖資料庫的一些基本内容(初識SQL Server2017 圖資料庫(一)),本篇通過對比關系型一些文法來展現圖資料庫模式的一些優點,比如查詢友善,語句易了解等。
在圖資料庫模型上建構查詢的優勢:
T-SQL 帶給圖表查詢一些新的文法。在SELECT語句中我們有一些特殊的語句來關聯點和邊。讓我們來演練一些,建構查詢語句檢索發帖和回複,如下:
我們檢索每個記錄的兩個部分,發帖和回複,是以我們需要在FROM子句中引用兩次ForumPosts’表,這個地方可以采用一些有意義的别名:
盡管我們能選擇任何别名,但是在處理圖對象時最好選擇有意義的名字。
我們需要“posts”之間的關系,而這個關系就是表Reply_to’。文法如下:
在WHERE 子句中,我們需要關聯所有的表,用下面這種MATCH語句來實作關聯:
這個文法很有意思:“-”破折号表示邊的$From_id字段表示關系,然後“->”破折号和大于号用邊的$To_id字段表示關系。
因為知道那個别名有reply,那個别名有replied post,我們可以建構一個查詢字段清單:
在關系型模型中相同功能的查詢如下:
這些查詢很相似,當然MATCH的文法更容易了解。
執行完上面語句查詢結果如下:

我們加上寫這個回複貼人的名字。需要在FROM子句中添加‘ForumMembers’節點和‘Written_By’這個邊。語句如下:
還要添加MATCH語句的内部關系:
這就可以在SELECT清單中添加回帖人的名字,最終的查詢如下:
在關系型模型中的對應查詢如下:
結果如下所示:
還缺少回複對象的名字。像上面一樣增加‘ForumMembers’ 和 ‘Written_By’在FROM子句中:
接下來,修改MATCH子句,‘ReplyMember’需要關聯‘ReplyPost’,但是如何去處理這個關系而不影響其他關系?需要用不同的方式來實作:
注意這個符号“<-”與之前的相反方向,但是意義是相同的:一個在邊表的$to_id與節點表的關系。
最終,還需增加寫着回複的成員姓名,代碼如下:
結果集如下:
在關系型查詢的對應語句:
在這個時候,可能在關系型模式裡面随着關系的增多讀取就會越困難,而在圖資料模式中MATCH子句相對就容易很多。讓我們看一下在圖資料模式中一些有趣又有用的地方。
統計每篇文章的回複數
在這個語句中我們統計了每一篇回複的數量,但是僅僅在一個層面中,并不是在整個回複的樹結構裡面。
根貼(主貼)的清單
我們通過下面不使用MATCH的語句得到所有的根貼:
MATCH文法隻是允許我們關聯三個或者更多的實體(比如兩個節點和一個關系)。當我們隻想關聯其中兩個的時候,隻需要一個正常的連接配接或者子查詢。如上面的語句一樣。
在結果中添加‘Level’字段
添加一個‘Level’字段,顯示樹結構。在T-SQL中有一個簡單的文法,叫做CTE實作遞歸。但是有一個問題,不能使用MATCH文法在一個派生表上,此時可以使用CTE。如果有必要,可以在CTE中使用MATCH,但是反之就不行了,有這樣的限制。下面展示一下使用正常的關系僅僅使用CTE來疊代,代碼如下:
檢索一個文章中的所有回複
使用CTE遞歸文法,我們可以用一種樹結構檢索一個文章的所有回複。如果使用正常的文法不能在檢索文章1的時候檢索貼子3,因為3是對2的回複,而2是對1的回複。使用CTE.當查詢文章1的所有回複時能檢索貼子3。代碼如下:
我們也可以反過來做,在樹狀結構中按順序檢索所有父貼。由于CTE不支援OUTER join,是以要在外部添加,代碼如下:
檢索一個使用者所有文章
查詢一個用所有的資訊,與文章不同,這不需要樹,要簡單不少:
或許你注意到上面兩個查詢的不同,就是在展示字段上是否使用DISTINCT。這個去重是因為Peter回複同一個文章可以超過一次。
在模型中檢索Likes(點贊)
這個查詢是有意思的:‘Likes’邊是成員和發帖表的關系。每一個關系都是唯一的,并不受其他關系影響。代碼如下:
還可以很容易地聚合資訊,以獲得每個文章或每個成員的總的Likes。
使用者點贊并且回複文章
我們也可以建立一些更有趣的查詢,例如,查找這些點贊并回複的人,如下:
注意,對于‘Member’節點使用了兩次在同一個MATCH表達式中。這形成了一種過濾:點贊并且有回複的成員,需要在‘LikedPost’和‘ReplyPost’中都有記錄才可以。
那麼在關系型模式中代碼如下:
看起來這種寫法更難了解和讀懂。
回帖給多個文章的成員
回帖個一個文章多次的成員:
上述兩種語句中唯一的不同就是展示結果的聚合。
通過上述建構在圖資料模式下的查詢和關聯,對比了正常語句以及在關系模式下的相同查詢,不難發現無論是在易讀性,邏輯了解上還是在性能上都有很大提高。當然這隻是第一個版本,是以難免有很多問題, 下一篇我講介紹這個版本存在的一部分問題。