SQLServer图数据库一些优点
上一篇簡要介紹了圖數據庫的一些基本內容(初識SQL Server2017 圖數據庫(一)),本篇通過對比關系型一些語法來體現圖數據庫模式的一些優點,比如查詢方便,語句易理解等。
在圖數據庫模型上構建查詢的優勢:
T-SQL 帶給圖表查詢一些新的語法。在SELECT語句中我們有一些特殊的語句來關聯點和邊。讓我們來演練一些,構建查詢語句檢索發帖和回復,如下:
FROM dbo.ForumPosts ReplyPost, dbo.ForumPosts RepliedPost
?
FROM dbo.ForumPosts ReplyPost, dbo.Reply_to, dbo.ForumPosts RepliedPost
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
統計每篇帖子的回復數
SELECT distinct RepliedPost.PostID,RepliedPost.PostTitle,RepliedPost.PostBody,count(ReplyPost.PostID) over(partition by RepliedPost.PostID)as TotalRepliesFROM dbo.ForumPosts ReplyPost, Reply_To, dbo.ForumPosts RepliedPostWHERE MATCH(ReplyPost-(Reply_To)->RepliedPost)?
在這個語句中我們統計了每一篇回復的數量,但是僅僅在一個層面中,并不是在整個回復的樹結構里面。
根貼(主貼)的列表
我們通過下面不使用MATCH的語句得到所有的根貼:
SELECT Post1.PostId,Post1.PostTitleFROM dbo.ForumPosts Post1WHERE $node_id not in (select $from_id from dbo.Reply_To?
MATCH語法只是允許我們關聯三個或者更多的實體(比如兩個節點和一個關系)。當我們只想關聯其中兩個的時候,只需要一個常規的連接或者子查詢。如上面的語句一樣。
在結果中添加‘Level’字段
添加一個‘Level’字段,顯示樹結構。在T-SQL中有一個簡單的語法,叫做CTE實現遞歸。但是有一個問題,不能使用MATCH語法在一個派生表上,此時可以使用CTE。如果有必要,可以在CTE中使用MATCH,但是反之就不行了,有這樣的限制。下面展示一下使用常規的關系僅僅使用CTE來迭代,代碼如下:
with root as( select $node_id as node_id,RootPosts.PostId,RootPosts.PostTitle,1 as Level, 0 as ReplyTofrom dbo.ForumPosts RootPostswhere $node_id not in (select $from_id from dbo.reply_to)union allselect $node_id,ReplyPost.PostId, ReplyPost.PostTitle,Level+1 as [Level], root.PostId as ReplyTofrom dbo.ForumPosts ReplyPost, reply_to, rootwhere ReplyPost.$node_id=reply_to.$from_idand root.node_id=reply_to.$to_id)select PostId,PostTitle, Level, ReplyTofrom root?
?
檢索一個帖子中的所有回復
使用CTE遞歸語法,我們可以用一種樹結構檢索一個帖子的所有回復。如果使用常規的語法不能在檢索帖子1的時候檢索貼子3,因為3是對2的回復,而2是對1的回復。使用CTE.當查詢帖子1的所有回復時能檢索貼子3。代碼如下:
with root as( select $node_id as node_id,RootPosts.PostId,RootPosts.PostTitle,1 as Level, 0 as ReplyTofrom dbo.ForumPosts RootPostswhere PostId=1 union allselect $node_id,ReplyPost.PostId, ReplyPost.PostTitle,Level+1 as [Level],root.PostId as ReplyTofrom dbo.ForumPosts ReplyPost, reply_to, rootwhere ReplyPost.$node_id=reply_to.$from_idand root.node_id=reply_to.$to_id)select PostId,PostTitle, Level, ReplyTofrom root?
我們也可以反過來做,在樹狀結構中按順序檢索所有父貼。由于CTE不支持OUTER join,所以要在外部添加,代碼如下:
with root as( select LeafPost.$node_id as node_id,LeafPost.PostId,LeafPost.PostTitlefrom dbo.ForumPosts LeafPostwhere LeafPost.PostId=3 -- Single postunion allselect RepliedPost.$node_id as node_id,RepliedPost.PostId,RepliedPost.PostTitlefrom dbo.ForumPosts RepliedPost, Reply_to, rootwhere root.node_id=Reply_to.$from_idand Reply_to.$to_id=RepliedPost.$node_id)select root.PostId,root.PostTitle,RepliedPost.PostId ParentPostIdfrom rootleft join reply_toon root.node_id=reply_to.$from_idleft join dbo.ForumPosts RepliedPoston reply_to.$to_id=RepliedPost.$node_id檢索一個用戶所有帖子
查詢一個用所有的信息,與帖子不同,這不需要樹,要簡單不少:
-- Peter回復的所有帖子SELECT distinct RepliedPost.PostID,RepliedPost.PostTitle,RepliedPost.PostBodyFROM dbo.ForumPosts ReplyPost, Reply_To, dbo.ForumPosts RepliedPost,dbo.ForumMembers Members,Written_ByWHERE MATCH(Members<-(Written_By)-ReplyPost-(Reply_To)->RepliedPost)and Members.MemberName='Peter'-- Peter發的所有帖子SELECT ReplyPost.PostID,ReplyPost.PostTitle,ReplyPost.PostBody,RepliedPost.PostId ReplyToFROM dbo.ForumPosts ReplyPost, Reply_To, dbo.ForumPosts RepliedPost,dbo.ForumMembers Members,Written_ByWHERE MATCH(Members<-(Written_By)-ReplyPost-(Reply_To)->RepliedPost)and Members.MemberName='Peter'?
或許你注意到上面兩個查詢的不同,就是在展示字段上是否使用DISTINCT。這個去重是因為Peter回復同一個帖子可以超過一次。
在模型中檢索Likes(點贊)
這個查詢是有意思的:‘Likes’邊是成員和發帖表的關系。每一個關系都是唯一的,并不受其他關系影響。代碼如下:
--點贊的帖子或者被別人點贊的帖子。SELECT Post.PostID,Post.PostTitle,Member.MemberNameFROM dbo.ForumPosts Post, Likes,dbo.ForumMembers MemberWHERE MATCH(Member-(Likes)->Post)-- 點贊的人或者被人點贊SELECT Member.MemberId,Member.MemberName LikeMember,LikedMember.MemberName LikedMemberNameFROM dbo.ForumMembers Member, Likes, dbo.ForumMembers LikedMemberWHERE MATCH(Member-(Likes)->LikedMember)?
還可以很容易地聚合信息,以獲得每個帖子或每個成員的總的Likes。
--每個帖子總的likesselect Post.PostId,Post.PostTitle,count(*) totalLikesfrom dbo.ForumPosts Post,Likes,dbo.ForumMembers Memberswhere Match(Members-(Likes)->Post)group by PostId,PostTitle--每個成員總的點贊數select LikedMembers.MemberId,LikedMembers.MemberName,count(*) totalLikesfrom dbo.ForumMembers Members,Likes,dbo.ForumMembers LikedMemberswhere Match(Members-(Likes)->LikedMembers)group by LikedMembers.MemberId,LikedMembers.MemberName?
用戶點贊并且回復帖子
我們也可以創建一些更有趣的查詢,例如,查找這些點贊并回復的人,如下:
SELECT Member.MemberName,Member.Memberid,LikedPost.PostId,LikedPost.PostTitle,ReplyPost.PostTitle ReplyTitleFROM dbo.ForumPosts LikedPost, Reply_To, dbo.ForumPosts ReplyPost,Likes, dbo.ForumMembers Member, Written_ByWHERE MATCH(Member-(Likes)->LikedPost<-(Reply_To)-ReplyPost-(Written_By)->Member)?
注意,對于‘Member’節點使用了兩次在同一個MATCH表達式中。這形成了一種過濾:點贊并且有回復的成員,需要在‘LikedPost’和‘ReplyPost’中都有記錄才可以。
那么在關系型模式中代碼如下:
select Likes.MemberId,Members.MemberNamefrom Forum.Likes Likes, Forum.ForumPosts Posts,Forum.ForumMembers Memberswhere Likes.MemberId=Posts.OwnerIdand Posts.ReplyTo=Likes.PostIdand Members.MemberId=Likes.MemberId?
看起來這種寫法更難理解和讀懂。
回帖給多個帖子的成員
SELECT Members.MemberId, Members.MemberName,Count(distinct RepliedPost.PostId) as TotalFROM dbo.ForumPosts ReplyPost, Reply_To, dbo.ForumPosts RepliedPost,Written_By,dbo.ForumMembers MembersWHERE MATCH(Members<-(Written_By)-ReplyPost-(Reply_To)->RepliedPost)GROUP BY MemberId, Members.MemberNameHaving Count(RepliedPost.PostId) >1?
回帖個一個帖子多次的成員:
SELECT Members.MemberId, Members.MemberName,RepliedPost.PostId RepliedId,count(*) as TotalRepliesFROM dbo.ForumPosts ReplyPost, Reply_To, dbo.ForumPosts RepliedPost,Written_By,dbo.ForumMembers MembersWHERE MATCH(Members<-(Written_By)-ReplyPost-(Reply_To)->RepliedPost)GROUP BY MemberId,MemberName,RepliedPost.PostIdHaving count(*) >1?
上述兩種語句中唯一的不同就是展示結果的聚合。
總結
通過上述構建在圖數據模式下的查詢和關聯,對比了常規語句以及在關系模式下的相同查詢,不難發現無論是在易讀性,邏輯理解上還是在性能上都有很大提高。當然這只是第一個版本,所以難免有很多問題, 下一篇我講介紹這個版本存在的一部分問題。
posted on 2018-01-25 08:41 NET未來之路 閱讀(...) 評論(...) 編輯 收藏轉載于:https://www.cnblogs.com/lonelyxmas/p/8349445.html
總結
以上是生活随笔為你收集整理的SQLServer图数据库一些优点的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java数字签名——RSA算法
- 下一篇: CasperJs 入门介绍