热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

SQL JOIN 简单介绍

本文还是秉持之前一贯的写作风格,以简单易懂的示例帮助大家了解
文章目录[隐藏]
  •  前言
  •  为什么需要join
  •  join的分类
  •  各种join的区别
  •  总结
  •  引用
  •  附件

 前言

  本文还是秉持之前一贯的写作风格,以简单易懂的示例帮助大家了解各种join的区别。

 为什么需要join

  为什么需要join?join中文意思为连接,连接意味着关联即将一个表和多个表之间关联起来。在处理数据库表的时候,我们经常会发现,需要从多个表中获取信息,将多个表的多个字段数据组装起来再返回给调用者。所以join的前提是这些表之间必须有关联字段。

 join的分类

SQL JOIN 简单介绍

  join分为两种,inner join和outer join,其中outer join分为三种,left outer join, right outer join, full outer join,另外left outer join又简称为left join即大家所熟知的左连接。

 各种join的区别

  在介绍各种join的区别之前,我们先来看一个简单的示例:

  场景描述:

  互联网时代,大家都喜欢在网上购物,尤其是淘宝和京东,所以我们选择的场景也是大家熟悉的网上购物。这是一个关于一个人和他在商城买了什么商品的一个故事;

  针对上述需求,我们建立了两张表,tb_person和tb_order,其中tb_person是关于这个人的描述,tb_order是关于他购买的商品的一个描述。

  我们的表结构很简单,tb_person只需要知道这个人是谁就可以了,所以只有三个字段id,firstname(名)和lastname(姓),同样tb_order也很简单,我们只要知道谁买了什么商品,所以只需要3个字段,分别是oid, oname(商品名称), pid(购买者编号)。

  tb_person:

 +-----------+-------------+------+-----+---------+----------------+ | Field     | Type        | Null | Key | Default | Extra          | +-----------+-------------+------+-----+---------+----------------+ | pid       | int(11)     | NO   | PRI | NULL    | auto_increment | | firstname | varchar(50) | YES  |     | NULL    |                | | lastname  | varchar(50) | YES  |     | NULL    |                | +-----------+-------------+------+-----+---------+----------------+

  tb_order:

 +-------+-------------+------+-----+---------+----------------+ | Field | Type        | Null | Key | Default | Extra          | +-------+-------------+------+-----+---------+----------------+ | oid   | int(11)     | NO   | PRI | NULL    | auto_increment | | oname | varchar(50) | YES  |     | NULL    |                | | pid   | int(11)     | YES  |     | NULL    |                | +-------+-------------+------+-----+---------+----------------+

  接下来,我们向上述两张表中写入一些示例数据:

  data in tb_person:

 +-----+-----------+----------+ | pid | firstname | lastname | +-----+-----------+----------+ |   1 | andy      | chen     | |   2 | irri      | wan      | |   3 | abby      | sun      | +-----+-----------+----------+

  tb_person表中有三位人员,分别是andy Chen, irri Wan, abby Sun;

  data in tb_order:

 +-----+----------+------+ | oid | oname    | pid  | +-----+----------+------+ |   1 | book     |    1 | |   2 | phone    |    1 | |   3 | computer |    4 | +-----+----------+------+

  tb_order表中记录了3条数据,人员编号为1也就是andy Chen买了两件商品分别是book和phone,另外还有一个人员编号为4的人买了一件商品computer。关于这个大家可能会产生疑问,为什么tb_person表中没有人员编号为4的人呢?这里我们姑且认为由于注册用户较多,我们采用了用户分表策略,所以人员编号为4的用户可能在另外一张人员表中。

  从之前的描述我们知道,表与表之间如果要join则必须要有关联的字段,上述示例我们看到这个关联的字段就是pid。

  根据tb_person和tb_order两张表,我们可以看到有三种情形:

  1. person表中的人购买了商品,也就是order表中有关于该用户的商品购买记录,我们可以从该表中查询到该用户买了哪些商品,如andy Chen购买了book和phone两种商品,即pid在tb_person和tb_order两种表中都存在;

  2. person表中的人未购买商品,如irri Wan和abby Sun两位用户并未购买任何商品,即pid只存在于tb_person表;

  3. order表中购买商品的用户在person表中找不到记录,如pid为4的用户购买了一台computer但在tb_person表中没有该用户的记录,即pid只存在于tb_order表;

  理解上述三种情形对于我们理解join有非常大的帮助,接下来我们将具体的分析每种join的区别:

  INNER JOIN

  所谓inner join的意思就是我们前面提到的情形1,pid必须在tb_person和tb_order两张表中同时存在;

 MariaDB > SELECT p.pid, p.firstname, o.oname     -> FROM tb_person p     -> INNER JOIN tb_order o     -> ON p.pid=o.pid;
 +-----+-----------+-------+ | pid | firstname | oname | +-----+-----------+-------+ |   1 | andy      | book  | |   1 | andy      | phone | +-----+-----------+-------+

  LEFT JOIN

  tb_person LEFT JOIN tb_order的意思是上述情形1,情形2的并集。LEFT JOIN的结果集不仅包含INNER JOIN的结果,而且还包含所有tb_person中没有购买任何商品的用户集。

 MariaDB > SELECT p.pid, p.firstname, o.oname     -> FROM tb_person p     -> LEFT JOIN tb_order o     -> ON p.pid=o.pid;
 +-----+-----------+-------+ | pid | firstname | oname | +-----+-----------+-------+ |   1 | andy      | book  | |   1 | andy      | phone | |   2 | irri      | NULL  | |   3 | abby      | NULL  | +-----+-----------+-------+

  RIGHT JOIN

  tb_person RIGHT JOIN tb_order的意思是上述情形1和情形3的并集。RIGHT JOIN的结果集不仅包含INNER JOIN的结果,而且还包含所有tb_order中所有已经购买商品的用户但该用户记录不存在于tb_person表。

 MariaDB > SELECT p.pid, p.firstname, o.oname     -> FROM tb_person p     -> RIGHT JOIN tb_order o     -> ON p.pid=o.pid;
 +------+-----------+----------+ | pid  | firstname | oname    | +------+-----------+----------+ |    1 | andy      | book     | |    1 | andy      | phone    | | NULL | NULL      | computer | +------+-----------+----------+

  FULL JOIN

  故名思议,FULL JOIN就是上述情形1,2,3的并集了,但是mysql数据库不支持full join查询,所以我们只能LEFT JOIN union RIGHT JOIN,才能得到FULL JOIN的结果。

 MariaDB > SELECT p.pid, p.firstname, o.oname     -> FROM tb_person p     -> LEFT JOIN tb_order o     -> ON p.pid=o.pid     -> UNION     -> SELECT p.pid, p.firstname, o.oname     -> FROM tb_person p     -> RIGHT JOIN tb_order o     -> ON p.pid=o.pid;
 +------+-----------+----------+ | pid  | firstname | oname    | +------+-----------+----------+ |    1 | andy      | book     | |    1 | andy      | phone    | |    2 | irri      | NULL     | |    3 | abby      | NULL     | | NULL | NULL      | computer | +------+-----------+----------+

  注:我们上述的sql语句全部基于mysql数据库执行。

 总结

  本文主要描述了sql join的分类以及各种join的区别,通过简单的示例,让大家更清晰的去了解他们。至于什么时候使用join要视具体的情况而定,根据不同的需求采用不同的策略。

  非常感谢大家的热心回复,可能有些问题的探讨超出了本文的范畴,但是非常乐意大家提出问题,然后大家一起去探索去发现。

 引用

  NULL

 附件

  demo.sql文件

 create database demo; use demo;  create table tb_person (     pid int(11) auto_increment,     firstname varchar(50),     lastname varchar(50),     primary key(pid) );  create table tb_order (     oid int(11) auto_increment,     oname varchar(50),     pid int(11),     primary key(oid) );  insert into tb_person(firstname, lastname) values('andy','chen'); insert into tb_person(firstname, lastname) values('irri','wan'); insert into tb_person(firstname, lastname) values('abby','sun');   insert into tb_order(oname, pid) values('book', 1); insert into tb_order(oname, pid) values('phone', 1); insert into tb_order(oname, pid) values('computer', 4);

欢迎大家阅读《SQL JOIN 简单介绍》,跪求各位点评,若觉得好的话请收藏本文,by



推荐阅读
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • MySQL外键1对多问题的解决方法及实例
    本文介绍了解决MySQL外键1对多问题的方法,通过准备数据、创建表和设置外键关联等步骤,实现了用户分组和插入数据的功能。详细介绍了数据准备的过程和外键关联的设置,以及插入数据的示例。 ... [详细]
  • Python SQLAlchemy库的使用方法详解
    本文详细介绍了Python中使用SQLAlchemy库的方法。首先对SQLAlchemy进行了简介,包括其定义、适用的数据库类型等。然后讨论了SQLAlchemy提供的两种主要使用模式,即SQL表达式语言和ORM。针对不同的需求,给出了选择哪种模式的建议。最后,介绍了连接数据库的方法,包括创建SQLAlchemy引擎和执行SQL语句的接口。 ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • 本文介绍了如何在MySQL中将零值替换为先前的非零值的方法,包括使用内联查询和更新查询。同时还提供了选择正确值的方法。 ... [详细]
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • 本文详细介绍了在ASP.NET中获取插入记录的ID的几种方法,包括使用SCOPE_IDENTITY()和IDENT_CURRENT()函数,以及通过ExecuteReader方法执行SQL语句获取ID的步骤。同时,还提供了使用这些方法的示例代码和注意事项。对于需要获取表中最后一个插入操作所产生的ID或马上使用刚插入的新记录ID的开发者来说,本文提供了一些有用的技巧和建议。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • 本文讨论了在数据库打开和关闭状态下,重新命名或移动数据文件和日志文件的情况。针对性能和维护原因,需要将数据库文件移动到不同的磁盘上或重新分配到新的磁盘上的情况,以及在操作系统级别移动或重命名数据文件但未在数据库层进行重命名导致报错的情况。通过三个方面进行讨论。 ... [详细]
  • 本文介绍了如何使用python从列表中删除所有的零,并将结果以列表形式输出,同时提供了示例格式。 ... [详细]
  • ALTERTABLE通过更改、添加、除去列和约束,或者通过启用或禁用约束和触发器来更改表的定义。语法ALTERTABLEtable{[ALTERCOLUMNcolu ... [详细]
  • 本文介绍了在MySQL8.0中如何查看性能并解析SQL执行顺序。首先介绍了查询性能工具的开启方法,然后详细解析了SQL执行顺序中的每个步骤,包括from、on、join、where、group by、having、select distinct、union、order by和limit。同时还介绍了虚拟表的概念和生成过程。通过本文的解析,读者可以更好地理解MySQL8.0中的性能查看和SQL执行顺序。 ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
author-avatar
手机用户2602927443
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有