怎样使数据库中的多表实现联合查询

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了怎样使数据库中的多表实现联合查询相关的知识,希望对你有一定的参考价值。

请说的具体点,谢谢

连接可以在SELECT 语句的FROM子句或WHERE子句中建立,似是而非在FROM子句中指出连接时有助于将连接操作与WHERE子句中的搜索条件区分开来。所以,在Transact-SQL中推荐使用这种方法。

SQL-92标准所定义的FROM子句的连接语法格式为:

FROM join_table join_type join_table
[ON (join_condition)]

其中join_table指出参与连接操作的表名,连接可以对同一个表操作,也可以对多表操作,对同一个表操作的连接又称做自连接。

join_type 指出连接类型,可分为三种:内连接、外连接和交叉连接。

内连接(INNER JOIN)使用比较运算符进行表间某(些)列数据的比较操作,并列出这些表中与连接条件相匹配的数据行。根据所使用的比较方式不同,内连接又分为等值连接、自然连接和不等连接三种。

外连接分为左外连接(LEFT OUTER JOIN或LEFT JOIN)、右外连接(RIGHT OUTER JOIN或RIGHT JOIN)和全外连接(FULL OUTER JOIN或FULL JOIN)三种。与内连接不同的是,外连接不只列出与连接条件相匹配的行,而是列出左表(左外连接时)、右表(右外连接时)或两个表(全外连接时)中所有符合搜索条件的数据行。

交叉连接(CROSS JOIN)没有WHERE 子句,它返回连接表中所有数据行的笛卡尔积,其结果集合中的数据行数等于第一个表中符合查询条件的数据行数乘以第二个表中符合查询条件的数据行数。

连接操作中的ON (join_condition) 子句指出连接条件,它由被连接表中的列和比较运算符、逻辑运算符等构成。

无论哪种连接都不能对text、ntext和image数据类型列进行直接连接,但可以对这三种列进行间接连接。例如:

SELECT p1.pub_id,p2.pub_id,p1.pr_info
FROM pub_info AS p1 INNER JOIN pub_info AS p2
ON DATALENGTH(p1.pr_info)=DATALENGTH(p2.pr_info)

(一)内连接

内连接查询操作列出与连接条件匹配的数据行,它使用比较运算符比较被连接列的列值。内连接分三种:

1、等值连接:在连接条件中使用等于号(=)运算符比较被连接列的列值,其查询结果中列出被连接表中的所有列,包括其中的重复列。

2、不等连接: 在连接条件使用除等于运算符以外的其它比较运算符比较被连接的列的列值。这些运算符包括>、>=、<=、<、!>、!<和<>。

3、自然连接:在连接条件中使用等于(=)运算符比较被连接列的列值,但它使用选择列表指出查询结果集合中所包括的列,并删除连接表中的重复列。

例,下面使用等值连接列出authors和publishers表中位于同一城市的作者和出版社:

SELECT *
FROM authors AS a INNER JOIN publishers AS p
ON a.city=p.city

又如使用自然连接,在选择列表中删除authors 和publishers 表中重复列(city和state):

SELECT a.*,p.pub_id,p.pub_name,p.country
FROM authors AS a INNER JOIN publishers AS p
ON a.city=p.city

(二)外连接

内连接时,返回查询结果集合中的仅是符合查询条件( WHERE 搜索条件或 HAVING 条件)和连接条件的行。而采用外连接时,它返回到查询结果集合中的不仅包含符合连接条件的行,而且还包括左表(左外连接时)、右表(右外连接时)或两个边接表(全外连接)中的所有数据行。

如下面使用左外连接将论坛内容和作者信息连接起来:

SELECT a.*,b.* FROM luntan LEFT JOIN usertable as b
ON a.username=b.username

下面使用全外连接将city表中的所有作者以及user表中的所有作者,以及他们所在的城市:

SELECT a.*,b.*
FROM city as a FULL OUTER JOIN user as b
ON a.username=b.username

左连接:(也叫左外连接,给出两个表的配匹行,并且以左边的表为准,如果左边表有而右边表没有的行,则在右边表的相应行选择的列显示为NULL,允许左边的基准表对应右边表多条满足条件的记录)左连接就是返回左边的匹配行,不考虑右边的表是否有相应的行,如:select field1,field2 from table1 left join table2

on field1=field2(基准字段,可以多个)

where table1.field3=table2.field3

右连接:(也叫右外连接,给出两个表的配匹行,并且以右边的表为准,如果右边表有而左边表没有的行,则在右边表的相应行选择的列显示为NULL,允许右边的基准表对应左边表多条满足条件的记录)

(三)交叉连接

交叉连接不带WHERE 子句,它返回被连接的两个表所有数据行的笛卡尔积,返回到结果集合中的数据行数等于第一个表中符合查询条件的数据行数乘以第二个表中符合查询条件的数据行数。

例,titles表中有6类图书,而publishers表中有8家出版社,则下列交叉连接检索到的记录数将等于6*8=48行。

SELECT type,pub_name
FROM titles CROSS JOIN publishers
ORDER BY
参考技术A 使用jion实现多表连接查询或者使用子查询

小程序中的多表联合查询

小程序设计中,通常会根据业务来做多表的拆分,多表拆分一般是根据业务的特点进行拆分。比如我们在文章关注的业务中,会将文章和关注信息拆分成一对多的表关系。初学者可能对一对一、一对多、多对多的设计概念不是特别清楚。

一对一的设计一般不常见,只需要设计到主表中即可,避免增加复杂性。一对多的关系比较常见,一的一方通常作为主表,多的一方通常作为子表。而多对多一般会拆分成两个一对多的关系,这就必须要用中间表进行过渡。

我们本篇介绍的多表查询,侧重在一对多的关系,我们先看一下我们实际的表设计

一对多表设计

我们实现的是文章关注的业务,通常将文章作为主表,而关注信息作为子表。表和表之间要进行关联,常见的设计思路是子表的外键和主表的主键进行关联


这里的文章表的主键是_id,所谓的主键就是可以唯一标识该条数据,数据不允许重复。关注表的articleid作为关注表的外键,外键可以重复,存储的是主表的主键。

SQL中的关联查询

在sql中可以对表进行关联查询,我们使用select 语句来进行关联,关联的语句为

select * from article a , focus f where a._id = f.articleid

两个表进行关联之后其实是对表进行了合并,将文章表的字段和关注表的字段合并成一个表,关联的条件是文章表的数据标识和关注表的articleid做等值连接

低码中的表关联

低码中的表设计也遵循数据库的表设计,不同的是,低码中的外键不需要自己单独设计,可以设置成关联关系即可,比如文章表的字段

一般我们的数据标识就是我们表的主键,关注表可以存储外键

我们这里的articleid的数据类型设置成关联关系其实就是一种外键的意思。

自定义连接器中实现表关联查询

要想在低码中实现表和表之间的关联查询,需要使用aggregate聚合的语法,聚合语法也有本表和需要连接的表,官方文档里使用了lookup进行表关联

lookup(
from: <要连接的集合名>,
localField: <输入记录的要进行相等匹配的字段>,
foreignField: <被连接集合的要进行相等匹配的字段>,
as: <输出的数组字段名>
)

具体的参数说明

参数字段说明
from要进行连接的另外一个集合的名字
localField当前流水线的输入记录的字段名,该字段将被用于与 from 指定的集合的 foreignField 进行相等匹配。如果输入记录中没有该字段,则该字段的值在匹配时会被视作 null
foreignField被连接集合的字段名,该字段会被用于与 localField 进行相等匹配。如果被连接集合的记录中没有该字段,该字段的值将在匹配时被视作 null
as指定连接匹配出的记录列表要存放的字段名,这个数组包含的是匹配出的来自 from 集合的记录。如果输入记录中本来就已有该字段,则该字段会被覆写

光看文档解释可能还不是特别明白,我们需要具体实践一下

新建连接器

登录控制台,点击自定义连接器,点击新建自定义连接器

输入名称和标识

点击添加方法,新增关联查询的方法

在自定义代码编辑器里输入如下代码

module.exports = async function (params, context) 
  const result = await context.database.collection('lcap-data-2cc504BEZ-gz_necsx6t-preview').aggregate()
  .match(
    openid:params.openid
  )
  .lookup(
    from: 'lcap-data-2cc4oRuu1-wz_hbmrxec-preview',
    localField: 'articleid',
    foreignField: '_id',
    as: 'articles',
  )
  .end()
  // 在这里返回这个方法的结果,需要与出参定义的结构映射
  return result.data;
;

为了让代码运行,先需要新建入参

入参建好之后,在代码里对应的match字段,其中左边是字段标识,右边可以通过params.openid来获取到入参

集合的名称需要在云开发cloudbase的数据库里找

这些都准备好了就要对好localField和foreignField,我们这里的localField是关注表里存储的文章id,而foreignField是文章表的数据标识

入参建好之后需要点击方法测试

测试成功之后就可以点击出参映射,这样一个方法就做好了。这里有必要说一下返回的结果

[

  

    "_id": "16db756f62e7386d0cfdef132edd5e8a",

    "owner": "1448239235785420802",

    "createdAt": 1659320429844,

    "createBy": "1448239235785420802",

    "wzbs": "111",

    "updateBy": "1448239235785420802",

    "openid": "1111",

    "articleid": "ca780ad562c290d509bd361d555705c3",

    "updatedAt": 1659320429844,

    "articles": [

      

        "_id": "ca780ad562c290d509bd361d555705c3",

        "owner": "1448239235785420802",

        "createdAt": 1656918229822,

        "bt": "最新文章一",

        "createBy": "1448239235785420802",

        "nr": "<p><span style=\\"color:#222222\\"><span style=\\"font-size:18px\\"><span style=\\"background-color:#ffffff\\">如果你是已经落实工作单位的毕业生,请及时与用人单位签订劳动合同,跟进缴纳社会保险,确认档案转递去向,并在规定时间内办理户口迁移、党团组织关系接转等手续。你入职的企业,也可以申请社会保险补贴、吸纳就业补贴以及扩岗补助等政策支持。</span></span></span></p>",

        "fbrq": 1656864000000,

        "updateBy": "1448239235785420802",

        "updatedAt": 1656918229822

      

    ]

  

]

返回的是一个数组,数组里包含一个对象,对象的基本属性是显示的关注表的字段,而articles是具体用户关注的文章的集合,在做展示的时候其实是要绑定articles才对

总结

要想实现多表之间的关联查询,先需要做数据库设计,然后按照文档的聚合语法编写自定义连接器实现,具体还需要结合你自己的业务才可以。

以上是关于怎样使数据库中的多表实现联合查询的主要内容,如果未能解决你的问题,请参考以下文章

mysql数据库的多表查询,子查询,联合查询

小程序中的多表联合查询

.net通用CMS快速开发框架——问题:Dapper通用的多表联合分页查询怎么破?

MyBatis的多表联合查询

sql 多表关联查询

多表联合查询:基于注解SQL