图片 13

SQLServer图数据库一些优点

    上一篇简要介绍了图数据库的一些基本内容(初识SQL Server2017
图数据库(一)),本篇通过对比关系型一些语法来体现图数据库模式的一些优点,比如查询方便,语句易理解等。

MySQL是一个关系型数据库管理系统,由瑞典MySQL
AB 公司开发,目前属于 Oracle 旗下产品。MySQL
最流行的关系型数据库管理系统,在 WEB 应用方面MySQL是最好的 RDBMS
(Relational Database Management
System,关系数据库管理系统)
应用软件之一。

在图数据库模型上构建查询的优势:

MySQL是一种关联数据库管理系统,关联数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。

T-SQL
带给图表查询一些新的语法。在SELECT语句中我们有一些特殊的语句来关联点和边。让我们来演练一些,构建查询语句检索发帖和回复,如下:

MySQL所使用的 SQL 语言是用于访问数据库的最常用标准化语言。MySQL
软件采用了双授权政策,它分为社区版和商业版,由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,一般中小型网站的开发都选择
MySQL
作为网站数据库。由于其社区版的性能卓越,搭配
PHP 和 Apache 可组成良好的开发环境。

  1. 我们检索每个记录的两个部分,发帖和回复,因此我们需要在FROM子句中引用两次ForumPosts’表,这个地方可以采用一些有意义的别名:

图片 1

    

使用子查询

查询:任何SQL语句都是查询。但此术语一般指SELECT语句。SQL还允许创建子查询,即嵌套在其他查询中的查询。

FROM dbo.ForumPosts ReplyPost, dbo.ForumPosts RepliedPost

一、利用子查询进行过滤

例如:列出订购物品TNT2的所有客户
步骤:(1)检索包含物品TNT2的所有订单的编号。
(2)检索具有前一步骤列出的订单编号的所有客户的ID。
(3)检索前一步骤返回的所有客户ID的客户信息。

SELECT order_num FROM orderitems WHERE prod_id='TNT2';

此语句的输出如下图所示:

图片 2

SELECT cust_id FROM orders WHERE order_num IN (20005,20007);

此语句的输出如下图所示:

图片 3

现在,把第一个查询(返回订单号的那一个)变为子查询组合两个查询,如下所示:

SELECT cust_id FROM orders WHERE order_num IN (SELECT order_num FROM orderitems WHERE prod_id='TNT2');

此语句的输出如下图所示:

图片 4

现在得到了订购物品TNT2的所有客户的ID。下一步是检索这些客户ID的客户信息。检索两列的SQL语句为:
如下所示:

SELECT cust_name,cust_contact FROM customers WHERE cust_id IN (10001,10004);

此语句的输出如下图所示:

图片 5

最终的查询语句如下所示:

SELECT cust_name,cust_contact FROM customers WHERE cust_id IN (SELECT cust_id FROM orders WHERE order_num IN (SELECT order_num FROM orderitems WHERE prod_id='TNT2'));

此语句的输出如下图所示:

图片 6

 

二、作为计算字段使用子查询

使用子查询的另一方法是创建计算字段。例如:显示customers表中每个客户的订单总数。订单与相应的客户ID存储在orders表中。
步骤:(1)在customers表中检索客户列表。
(2)对于检索出来的每个客户,统计其在orders表中的订单数目。
为了对每个客户执行COUNT()计算,应该将COUNT()作为一个子查询。代码如下:

SELECT cust_name,cust_state, (SELECT COUNT(*) FROM orders WHERE orders.cust_id=customers.cust_id) AS orders FROM customers ORDER BY cust_name;

此语句的输出如下图所示:

图片 7

  1. 尽管我们能选择任何别名,但是在处理图对象时最好选择有意义的名字。
  2. 我们需要“posts”之间的关系,而这个关系就是表Reply_to’。语法如下:

联结表

如果数据存储在多个表中,怎样用单条SELECT语句检索出数据?
使用联结。简单地说,联结是一种机制,用来在一条SELECT语句中关联表,因此称为联结。使用特殊的语法,可以联结多个表返回一组输出,联结在运行时关联表中正确的行。

    

一、创建联结

SELECT vend_name,prod_name,prod_price FROM vendors,products WHERE vendors.vend_id=products.vend_id ORDER BY vend_name,prod_name;

此语句的输出如下图所示:

图片 8

SELECT语句与前面的语句一样指定要检索的列。这里,最大的差别是所指定的两个列(prod_name和prod_price)在一个表中,而另一个列(vend_name)在另一个表中。这条语句的FROM子句列出了两个表,分别是vendors和products。它们就是这条SELECT语句联结的两个表的名字。这两个表用WHERE子句正确联结,WHERE子句指示MySQL匹配vendors表中的vend_id和products表中的vend_id。

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

二、内部联结(重要)

目前为止所用的联结称为等值联结,它基于两个表之间的相等测试。这种联结也称为内部联结。下面的SELECT语句返回与前面例子完全相同的数据:

SELECT vend_name,prod_name,prod_price FROM vendors INNER JOIN products ON vendors.vend_id=products.vend_id ORDER BY vend_name,prod_name;

此语句的输出如下图所示:

图片 9

此语句中的SELECT与前面的SELECT语句相同,但FROM子句不同。这里,两个表之间的关系是FROM子句的组成部分,以
INNER JOIN
指定。在使用这种语法时,联结条件用特定的ON子句而不是WHERE子句给出。传递给ON的实际条件与传递给WHERE的相同。

 

三、联结多个表

SQL对于一条SELECT语句中可以联结的表的数目没有限制。创建联结的基本规则也相同。首先列出所有表,然后定义表之间的关系。例如:

SELECT prod_name,vend_name,prod_price,quantity FROM orderitems,vendors ,products WHERE products.vend_id=vendors.vend_id AND orderitems.prod_id=products.prod_id AND order_num=20005;

此语句的输出如下图所示:

图片 10

  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. 执行完上面语句查询结果如下:

 图片 11

  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. 结果如下所示:

 图片 12

  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. 结果集如下:

 图片 13

  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)