SQLServer圖資料庫一些優點

来源:http://www.cnblogs.com/wenBlog/archive/2017/11/14/7833971.html
-Advertisement-
Play Games

上一篇簡要介紹了圖資料庫的一些基本內容(初識SQL Server2017 圖資料庫(一)),本篇通過對比關係型一些語法來體現圖資料庫模式的一些優點,比如查詢方便,語句易理解等。 在圖資料庫模型上構建查詢的優勢: T-SQL 帶給圖表查詢一些新的語法。在SELECT語句中我們有一些特殊的語句來關聯點和 ...


    上一篇簡要介紹了圖資料庫的一些基本內容(初識SQL Server2017 圖資料庫(一)),本篇通過對比關係型一些語法來體現圖資料庫模式的一些優點,比如查詢方便,語句易理解等。

在圖資料庫模型上構建查詢的優勢:

T-SQL 帶給圖表查詢一些新的語法。在SELECT語句中我們有一些特殊的語句來關聯點和邊。讓我們來演練一些,構建查詢語句檢索發帖和回覆,如下:

  1. 我們檢索每個記錄的兩個部分,發帖和回覆,因此我們需要在FROM子句中引用兩次ForumPosts’表,這個地方可以採用一些有意義的別名:

    

FROM dbo.ForumPosts ReplyPost, dbo.ForumPosts RepliedPost

 

  1. 儘管我們能選擇任何別名,但是在處理圖對象時最好選擇有意義的名字。
  2. 我們需要“posts”之間的關係,而這個關係就是表Reply_to’。語法如下:

    

FROM dbo.ForumPosts ReplyPost, dbo.Reply_to, dbo.ForumPosts RepliedPost

 

  1. 在WHERE 子句中,我們需要關聯所有的表,用下麵這種MATCH語句來實現關聯:
FROM dbo.ForumPosts ReplyPost, dbo.Reply_to, dbo.ForumPosts RepliedPost

WHERE MATCH(ReplyPost-(Reply_to)->RepliedPost)

 

  1. 這個語法很有意思:“-”破折號表示邊的$From_id欄位表示關係,然後“->”破折號和大於號用邊的$To_id欄位表示關係。
  2. 因為知道那個別名有reply,那個別名有replied post,我們可以構建一個查詢欄位列表:
FROM dbo.ForumPosts ReplyPost, dbo.Reply_to, dbo.ForumPosts RepliedPost

WHERE MATCH(ReplyPost-(Reply_to)->RepliedPost)

 

  1. 在關係型模型中相同功能的查詢如下:
     

select RepliedPost.PostId,RepliedPost.PostTitle,

   ReplyPost.PostId as ReplyId, ReplyPost.PostTitle as ReplyTitle

  from Forum.ForumPosts ReplyPost, Forum.ForumPosts RepliedPost

  where ReplyPost.PostId=RepliedPost.ReplyTo

 

  1. 這些查詢很相似,當然MATCH的語法更容易理解。
  2. 執行完上面語句查詢結果如下:

 

  1. 我們加上寫這個回覆貼人的名字。需要在FROM子句中添加‘ForumMembers’節點和‘Written_By’這個邊。語句如下:
FROM dbo.ForumPosts ReplyPost, dbo.Reply_to, dbo.ForumPosts RepliedPost, dbo.ForumMembers RepliedMember, Written_By RepliedWritten_By

 

  1. 還要添加MATCH語句的內部關係:
     
WHERE MATCH(ReplyPost-(Reply_to)->RepliedPost-(RepliedWritten_by)->RepliedMember)

 

  1. 這就可以在SELECT列表中添加回帖人的名字,最終的查詢如下:
     

-- Posts 、members 和replies

   SELECT RepliedPost.PostId,RepliedPost.PostTitle,RepliedMember.MemberName,

   ReplyPost.PostId as ReplyId, ReplyPost.PostTitle as ReplyTitle

      FROM dbo.ForumPosts ReplyPost, dbo.Reply_to, dbo.ForumPosts RepliedPost,

        dbo.ForumMembers RepliedMember, Written_By RepliedWritten_By

   WHERE MATCH(ReplyPost-(Reply_to)->RepliedPost-(RepliedWritten_by)->RepliedMember)

 

  1. 在關係型模型中的對應查詢如下:
SELECT RepliedPost.PostId,RepliedPost.PostTitle,

   ReplyPost.PostId as ReplyId, ReplyPost.PostTitle as ReplyTitle,

   RepliedMember.MemberName

  FROM Forum.ForumPosts ReplyPost, Forum.ForumPosts RepliedPost,

   Forum.ForumMembers RepliedMember

  WHERE ReplyPost.PostId=RepliedPost.ReplyTo

        and RepliedPost.OwnerId=RepliedMember.MemberId

 

  1. 結果如下所示:

 

  1. 還缺少回覆對象的名字。像上面一樣增加‘ForumMembers’ 和  ‘Written_By’在FROM子句中:
From dbo.ForumPosts ReplyPost, dbo.Reply_to, dbo.ForumPosts RepliedPost,

dbo.ForumMembers RepliedMember, Written_By RepliedWritten_By,

dbo.ForumMembers ReplyMember, Written_By ReplyWritten_By

 

  1. 接下來,修改MATCH子句,‘ReplyMember’需要關聯‘ReplyPost’,但是如何去處理這個關係而不影響其他關係?需要用不同的方式來實現:
WHERE MATCH(ReplyMember<-(ReplyWritten_By)-ReplyPost-(Reply_to)->RepliedPost-(RepliedWritten_by)->RepliedMember)

 

  1. 註意這個符號“<-”與之前的相反方向,但是意義是相同的:一個在邊表的$to_id與節點表的關係。
  2. 最終,還需增加寫著回覆的成員姓名,代碼如下:
-- Posts and members and their replies and members

   SELECT RepliedPost.PostId, RepliedPost.PostTitle,RepliedMember.MemberName,

   ReplyPost.PostId as ReplyId, ReplyPost.PostTitle as ReplyTitle,

   ReplyMember.MemberName [ReplyMemberName]

      FROM dbo.ForumPosts ReplyPost, dbo.Reply_to, dbo.ForumPosts RepliedPost,

        dbo.ForumMembers RepliedMember, Written_By RepliedWritten_By,

        dbo.ForumMembers ReplyMember, Written_By ReplyWritten_By

      WHERE MATCH(ReplyMember<-(ReplyWritten_By)-ReplyPost-(Reply_to)->RepliedPost-(RepliedWritten_by)->RepliedMember)

 

  1. 結果集如下:

 

  1. 在關係型查詢的對應語句:
SELECT RepliedPost.PostId,RepliedPost.PostTitle,

         RepliedMember.MemberName, ReplyPost.PostId as ReplyId,

      ReplyPost.PostTitle as ReplyTitle, ReplyMember.MemberName

  FROM Forum.ForumPosts ReplyPost, Forum.ForumPosts RepliedPost,

       Forum.ForumMembers RepliedMember, Forum.ForumMembers ReplyMember

  WHERE ReplyPost.PostId=RepliedPost.ReplyTo

        and RepliedPost.OwnerId=RepliedMember.MemberId

        and ReplyPost.OwnerId=ReplyMember.MemberId

 

  1. 在這個時候,可能在關係型模式裡面隨著關係的增多讀取就會越困難,而在圖數據模式中MATCH子句相對就容易很多。讓我們看一下在圖數據模式中一些有趣又有用的地方。

統計每篇帖子的回覆數

  SELECT distinct RepliedPost.PostID,RepliedPost.PostTitle,

          RepliedPost.PostBody,

          count(ReplyPost.PostID) over(partition by RepliedPost.PostID)

              as TotalReplies

   FROM dbo.ForumPosts ReplyPost, Reply_To, dbo.ForumPosts RepliedPost

   WHERE MATCH(ReplyPost-(Reply_To)->RepliedPost)

 

在這個語句中我們統計了每一篇回覆的數量,但是僅僅在一個層面中,並不是在整個回覆的樹結構裡面。

根貼(主貼)的列表

我們通過下麵不使用MATCH的語句得到所有的根貼:

SELECT Post1.PostId,Post1.PostTitle

  FROM dbo.ForumPosts Post1

  WHERE $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 ReplyTo

     from dbo.ForumPosts RootPosts

     where $node_id not in (select $from_id from dbo.reply_to)

  union all

     select $node_id,ReplyPost.PostId, ReplyPost.PostTitle,

            Level+1 as [Level], root.PostId as ReplyTo

     from dbo.ForumPosts ReplyPost, reply_to, root

     where ReplyPost.$node_id=reply_to.$from_id

           and root.node_id=reply_to.$to_id

  )

  select PostId,PostTitle, Level, ReplyTo

  from 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 ReplyTo

     from dbo.ForumPosts RootPosts

     where PostId=1  

  union all

     select $node_id,ReplyPost.PostId, ReplyPost.PostTitle,

            Level+1 as [Level],root.PostId as ReplyTo

     from dbo.ForumPosts ReplyPost, reply_to, root

     where ReplyPost.$node_id=reply_to.$from_id

           and root.node_id=reply_to.$to_id

  )

  select PostId,PostTitle, Level, ReplyTo

  from root

 

我們也可以反過來做,在樹狀結構中按順序檢索所有父貼。由於CTE不支持OUTER join,所以要在外部添加,代碼如下:

with root as

  ( select LeafPost.$node_id as node_id,LeafPost.PostId,

           LeafPost.PostTitle

     from dbo.ForumPosts LeafPost

     where LeafPost.PostId=3  -- Single post

  union all

     select RepliedPost.$node_id as node_id,RepliedPost.PostId,

            RepliedPost.PostTitle

     from dbo.ForumPosts RepliedPost, Reply_to, root

     where root.node_id=Reply_to.$from_id

           and Reply_to.$to_id=RepliedPost.$node_id

  )

  select root.PostId,root.PostTitle,

         RepliedPost.PostId ParentPostId

  from root

  left join reply_to

       on root.node_id=reply_to.$from_id

  left join dbo.ForumPosts RepliedPost

       on reply_to.$to_id=RepliedPost.$node_id

檢索一個用戶所有帖子

查詢一個用所有的信息,與帖子不同,這不需要樹,要簡單不少:

--  Peter回覆的所有帖子

   SELECT distinct RepliedPost.PostID,RepliedPost.PostTitle,

           RepliedPost.PostBody

   FROM dbo.ForumPosts ReplyPost, Reply_To, dbo.ForumPosts RepliedPost,

        dbo.ForumMembers Members,Written_By

   WHERE MATCH(Members<-(Written_By)-ReplyPost-(Reply_To)->RepliedPost)

   and Members.MemberName='Peter'

  -- Peter發的所有帖子

   SELECT ReplyPost.PostID,ReplyPost.PostTitle,ReplyPost.PostBody,

          RepliedPost.PostId ReplyTo

   FROM dbo.ForumPosts ReplyPost, Reply_To, dbo.ForumPosts RepliedPost,

        dbo.ForumMembers Members,Written_By

   WHERE MATCH(Members<-(Written_By)-ReplyPost-(Reply_To)->RepliedPost)

   and Members.MemberName='Peter'

 

或許你註意到上面兩個查詢的不同,就是在展示欄位上是否使用DISTINCT。這個去重是因為Peter回覆同一個帖子可以超過一次。

在模型中檢索Likes(點贊)

這個查詢是有意思的:‘Likes’邊是成員和發帖表的關係。每一個關係都是唯一的,並不受其他關係影響。代碼如下:

--點贊的帖子或者被別人點贊的帖子。

  SELECT Post.PostID,Post.PostTitle,Member.MemberName

  FROM   dbo.ForumPosts Post, Likes,

         dbo.ForumMembers Member

  WHERE MATCH(Member-(Likes)->Post)

  -- 點贊的人或者被人點贊

  SELECT Member.MemberId,Member.MemberName LikeMember,

         LikedMember.MemberName LikedMemberName

  FROM dbo.ForumMembers Member, Likes, dbo.ForumMembers LikedMember

  WHERE MATCH(Member-(Likes)->LikedMember)

 

還可以很容易地聚合信息,以獲得每個帖子或每個成員的總的Likes。

--每個帖子總的likes

  select Post.PostId,Post.PostTitle,

         count(*) totalLikes

  from dbo.ForumPosts Post,Likes,

       dbo.ForumMembers Members

  where Match(Members-(Likes)->Post)

  group by PostId,PostTitle

  --每個成員總的點贊數select LikedMembers.MemberId,LikedMembers.MemberName,

         count(*) totalLikes

  from dbo.ForumMembers Members,Likes,

       dbo.ForumMembers LikedMembers

  where Match(Members-(Likes)->LikedMembers)

  group by LikedMembers.MemberId,

           LikedMembers.MemberName

 

用戶點贊並且回覆帖子

我們也可以創建一些更有趣的查詢,例如,查找這些點贊並回覆的人,如下:


  SELECT Member.MemberName,Member.Memberid,

         LikedPost.PostId,LikedPost.PostTitle,

         ReplyPost.PostTitle ReplyTitle

  FROM dbo.ForumPosts LikedPost, Reply_To, dbo.ForumPosts ReplyPost,

       Likes, dbo.ForumMembers Member, Written_By

  WHERE MATCH(Member-(Likes)->LikedPost<-(Reply_To)-ReplyPost-(Written_By)->Member)

 

註意,對於‘Member’節點使用了兩次在同一個MATCH表達式中。這形成了一種過濾:點贊並且有回覆的成員,需要在‘LikedPost’和‘ReplyPost’中都有記錄才可以。

那麼在關係型模式中代碼如下:

select Likes.MemberId,Members.MemberName

  from Forum.Likes Likes, Forum.ForumPosts Posts,

       Forum.ForumMembers Members

  where Likes.MemberId=Posts.OwnerId

   and Posts.ReplyTo=Likes.PostId

   and Members.MemberId=Likes.MemberId

 

看起來這種寫法更難理解和讀懂。

回帖給多個帖子的成員

SELECT Members.MemberId, Members.MemberName,

         Count(distinct RepliedPost.PostId) as Total

  FROM   dbo.ForumPosts ReplyPost, Reply_To, dbo.ForumPosts RepliedPost,

         Written_By,dbo.ForumMembers Members

  WHERE  MATCH(Members<-(Written_By)-ReplyPost-(Reply_To)->RepliedPost)

  GROUP BY MemberId, Members.MemberName

  Having Count(RepliedPost.PostId) >1

 

回帖個一個帖子多次的成員:

SELECT Members.MemberId, Members.MemberName,

         RepliedPost.PostId RepliedId,count(*) as TotalReplies

  FROM   dbo.ForumPosts ReplyPost, Reply_To, dbo.ForumPosts RepliedPost,

       Written_By,dbo.ForumMembers Members

  WHERE MATCH(Members<-(Written_By)-ReplyPost-(Reply_To)->RepliedPost)

  GROUP BY MemberId,MemberName,RepliedPost.PostId

  Having count(*) >1

 

上述兩種語句中唯一的不同就是展示結果的聚合。

總結

  通過上述構建在圖數據模式下的查詢和關聯,對比了常規語句以及在關係模式下的相同查詢,不難發現無論是在易讀性,邏輯理解上還是在性能上都有很大提高。當然這隻是第一個版本,所以難免有很多問題, 下一篇我講介紹這個版本存在的一部分問題。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 為什麼要對Android中的圖片進行採樣縮放呢? 是為了更加高效的載入Bitmap。假設通過imageView來顯示圖片,很多時候ImageView並沒有圖片的原始尺寸那麼大,這時候把整張圖片載入進來後再設給ImageView是沒有必要的,因為ImagView並沒有辦法顯示原始的圖片。 所以我們可以 ...
  • “移動警務通”綜合系統為公安行業提供一種高效的移動警務應用解決方案,適用於交警、巡警、刑警、治安警等各類警務人員,利用移動網路,通過身份證拍照識別軟體接入警務通後臺管理系統和警務通呼叫中心(110指揮調度中心/便民報警處理中心)系統,構成新一代立體的公安辦公網路。目前身份證拍照識別、車牌拍照識別技術 ...
  • 在管理工具里打開Internet 信息服務(IIS)管理器。然後選擇需要配置的網站。 右側的界面中會顯示該網站的所有功能配置,我們選擇並點擊進入“MIME類型” 在左側的操作區選擇點擊“添加”MIME。 在彈出的添加視窗里的文件擴展名輸入:APK 在MIME類型輸入:application/vnd. ...
  • 微信分享前提: 1.需要成功在微信開發者平臺註冊了賬號, 並取的對應的 appkey appSecret。 2. 針對iOS9 添加了微信的白名單,以及設置了 scheme url 。 這都可以參照上面的鏈接,進行設置好。 3. 分享不跳轉的時候原因總結, 具體方法如下: 1. 首先檢查下是否有向微 ...
  • 轉載請標明出處:http://blog.csdn.net/zhaoyanjun6/article/details/78265540 本文出自 "【趙彥軍的博客】" 在前面我介紹了插件開發的基本流程 "【Android Studio 插件開發詳解一:入門練手】" "【Android Studio 插件 ...
  • TensorFlow對Android、iOS、樹莓派都提供移動端支持。 移動端應用原理。移動端、嵌入式設備應用深度學習方式,一模型運行在雲端伺服器,向伺服器發送請求,接收伺服器響應;二在本地運行模型,PC訓練模型,放到移動端預測。向服務端請求數據可行性差,移動端資源稀缺。本地運行實時性更好。加速計算 ...
  • 一直搞不明白Oracle資料庫和sql server的區別,今天我特意查資料把他們的區別整理出來 Oracle資料庫:Oracle Database,又名Oracle RDBMS,或簡稱Oracle。是甲骨文公司的一款關係資料庫管理系統。 它是在資料庫領域一直處於領先地位的產品。可以說Oracle數 ...
  • sql語句性能不行,執行效率就會降低。對於sql語句做一些簡單的註意,只對於寫sql語句方面,寫的不全,但可以應付一下麵試。 1.儘量避免select * 的存在,最好使用具體的列,避免多餘的列 2.使用where限定具體查詢的數據,避免出現多餘的行 3.使用top 4.慎用distionct,給查 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...