SQL联结笔记(内联结,自联结,自然联结,外联结区别以及应用)
SQL中有三种联结,分别是:内联结,自然联结,外联结.
联结是针对不同表联合起来的一种方式.应用的对象是:表(table)
为了方便验证练习理解,首先展示所要用到的表的内容:
1.Customers表:
数据(可复制,创建表,插入数据):
CREATE TABLE Customers
(
cust_id char(10) NOT NULL ,
cust_name char(50) NOT NULL ,
cust_address char(50) NULL ,
cust_city char(50) NULL ,
cust_state char(5) NULL ,
cust_zip char(10) NULL ,
cust_country char(50) NULL ,
cust_contact char(50) NULL ,
cust_email char(255) NULL
);
-- ------------------------
-- Populate Customers table
-- ------------------------
INSERT INTO Customers(cust_id, cust_name, cust_address, cust_city, cust_state,
cust_zip, cust_country, cust_contact, cust_email)
VALUES('1000000001', 'Village Toys', '200 Maple Lane', 'Detroit', 'MI',
'44444', 'USA', 'John Smith', 'sales@villagetoys.com');
INSERT INTO Customers(cust_id, cust_name, cust_address, cust_city, cust_state,
cust_zip, cust_country, cust_contact)
VALUES('1000000002', 'Kids Place', '333 South Lake Drive', 'Columbus', 'OH',
'43333', 'USA', 'Michelle Green');
INSERT INTO Customers(cust_id, cust_name, cust_address, cust_city, cust_state,
cust_zip, cust_country, cust_contact, cust_email)
VALUES('1000000003', 'Fun4All', '1 Sunny Place', 'Muncie', 'IN', '42222',
'USA', 'Jim Jones', 'jjones@fun4all.com');
INSERT INTO Customers(cust_id, cust_name, cust_address, cust_city, cust_state,
cust_zip, cust_country, cust_contact, cust_email)
VALUES('1000000004', 'Fun4All', '829 Riverside Drive', 'Phoenix', 'AZ',
'88888', 'USA', 'Denise L. Stephens', 'dstephens@fun4all.com');
INSERT INTO Customers(cust_id, cust_name, cust_address, cust_city, cust_state,
cust_zip, cust_country, cust_contact)
VALUES('1000000005', 'The Toy Store', '4545 53rd Street', 'Chicago', 'IL',
'54545', 'USA', 'Kim Howard');
-- ----------------------
展示:

2.Vendors:
-- -------------------
-- Create Orders table
-- -------------------
CREATE TABLE Orders
(
order_num int NOT NULL ,
order_date datetime NOT NULL ,
cust_id char(10) NOT NULL
);
-- ----------------------
-- Populate Vendors table
-- ----------------------
INSERT INTO Vendors(vend_id, vend_name, vend_address, vend_city, vend_state,
vend_zip, vend_country)
VALUES('BRS01','Bears R Us','123 Main Street','Bear Town','MI','44444', 'USA');
INSERT INTO Vendors(vend_id, vend_name, vend_address, vend_city, vend_state,
vend_zip, vend_country)
VALUES('BRE02','Bear Emporium','500 Park Street','Anytown','OH','44333',
'USA');
INSERT INTO Vendors(vend_id, vend_name, vend_address, vend_city, vend_state,
vend_zip, vend_country)
VALUES('DLL01','Doll House Inc.','555 High Street','Dollsville','CA','99999',
'USA');
INSERT INTO Vendors(vend_id, vend_name, vend_address, vend_city, vend_state,
vend_zip, vend_country)
VALUES('FRB01','Furball Inc.','1000 5th Avenue','New York','NY','11111',
'USA');
INSERT INTO Vendors(vend_id, vend_name, vend_address, vend_city, vend_state,
vend_zip, vend_country)
VALUES('FNG01','Fun and Games','42 Galaxy Road','London', NULL,'N16 6PS',
'England');
INSERT INTO Vendors(vend_id, vend_name, vend_address, vend_city, vend_state,
vend_zip, vend_country)
VALUES('JTS01','Jouets et ours','1 Rue Amusement','Paris', NULL,'45678',
'France');
-- -----------------------

3.Products:
-- ---------------------
-- Create Products table
-- ---------------------
CREATE TABLE Products
(
prod_id char(10) NOT
NULL ,
vend_id char(10) NOT
NULL ,
prod_name char(255) NOT NULL ,
prod_price decimal(8,2) NOT NULL ,
prod_desc
text NULL
);
-- -----------------------
-- Populate Products table
-- -----------------------
INSERT INTO Products(prod_id, vend_id, prod_name, prod_price, prod_desc)
VALUES('BR01', 'BRS01', '8 inch teddy bear', 5.99, '8 inch teddy bear, comes
with cap and jacket');
INSERT INTO Products(prod_id, vend_id, prod_name, prod_price, prod_desc)
VALUES('BR02', 'BRS01', '12 inch teddy bear', 8.99, '12 inch teddy bear, comes
with cap and jacket');
INSERT INTO Products(prod_id, vend_id, prod_name, prod_price, prod_desc)
VALUES('BR03', 'BRS01', '18 inch teddy bear', 11.99, '18 inch teddy bear, comes
with cap and jacket');
INSERT INTO Products(prod_id, vend_id, prod_name, prod_price, prod_desc)
VALUES('BNBG01', 'DLL01', 'Fish bean bag toy', 3.49, 'Fish bean bag toy,
complete with bean bag worms with which to feed it');
INSERT INTO Products(prod_id, vend_id, prod_name, prod_price, prod_desc)
VALUES('BNBG02', 'DLL01', 'Bird bean bag toy', 3.49, 'Bird bean bag toy, eggs
are not included');
INSERT INTO Products(prod_id, vend_id, prod_name, prod_price, prod_desc)
VALUES('BNBG03', 'DLL01', 'Rabbit bean bag toy', 3.49, 'Rabbit bean bag toy,
comes with bean bag carrots');
INSERT INTO Products(prod_id, vend_id, prod_name, prod_price, prod_desc)
VALUES('RGAN01', 'DLL01', 'Raggedy Ann', 4.99, '18 inch Raggedy Ann doll');
INSERT INTO Products(prod_id, vend_id, prod_name, prod_price, prod_desc)
VALUES('RYL01', 'FNG01', 'King doll', 9.49, '12 inch king doll with royal
garments and crown');
INSERT INTO Products(prod_id, vend_id, prod_name, prod_price, prod_desc)
VALUES('RYL02', 'FNG01', 'Queen doll', 9.49, '12 inch queen doll with royal
garments and crown');

4.Orders
-- -------------------
-- Create Orders table
-- -------------------
CREATE TABLE Orders
(
order_num int NOT NULL ,
order_date datetime NOT NULL ,
cust_id char(10) NOT NULL
);
-- ---------------------
-- Populate Orders table
-- ---------------------
INSERT INTO Orders(order_num, order_date, cust_id)
VALUES(20005, '2012-05-01', '1000000001');
INSERT INTO Orders(order_num, order_date, cust_id)
VALUES(20006, '2012-01-12', '1000000003');
INSERT INTO Orders(order_num, order_date, cust_id)
VALUES(20007, '2012-01-30', '1000000004');
INSERT INTO Orders(order_num, order_date, cust_id)
VALUES(20008, '2012-02-03', '1000000005');
INSERT INTO Orders(order_num, order_date, cust_id)
VALUES(20009, '2012-02-08', '1000000001');

好吧,如上原始数据已经有了,现在我们来理解SQL几种联结之间的关系和细节.
1.为什么要使用联结:
有时候为了方便存储,我们会把数据分解为多个表.例如,现在某公司需要用到以下产品,别人对应的供应商和价格如下:

这一张表存了供应商的信息和产品以及价格.可以看到这个供应商给我们提供了两种产品:QQ和邮箱;
这两种产品都是出自于同一个供应商,因此我们存储数据的时候,"供应商的地址"和"联系人" 就被重复存储了".现实应用中,一个供应商可能提供的产品远远超过2个,
这就会给我录入数据和存储数据和更新数据带来很大的麻烦.譬如:这个提供多种产品的供应商的地址需要更新的时候
于是我们可以把张表分解成两个表,关联两个表主键(方便查询,也就是相关联的共同的信息),如下:
1.

2.

这样一来,后续要我更新某个供应商的地址和联系人的时候,只需要对表2中的对应内容进行更新就好了.这样分解表后的两个表更直观一些了,但是在我们处理查询数据的时候,就要关联两个表中的
信息了,操作的复杂度就增大了.按照我们常规的处理方式,
如果我们要查提供某一个产品的供应商的全部信息,那就要先到表2中把供应商的地址和联系人先查出来,然后再结合表1中对应产品的其他信息
这时我们一种方式是分步处理:
1,按照步骤来,首先在表1中查出对应产品的供应商
2.在表2中查出对应的供应商的地址和联系人信息
另外一种是,嵌套子查询,一步设置完查询
但是这两种方式,操作起来都不是太方便,在输入的时候可能要多输入一些条件和内容才能达到我们想要的结果.因此就有了联结的概念.
如最上面所说,联结有几种方式:内联结,自联结,自然联结,外联结
内联结(INNER JOIN):内联结也可以称为等值联结.例如:
如以上两个表格中,每个订单包含订单编号,客户ID,订单日期,在Orders表中存储为一行,各订单的物品存储在相关的OrdersItems表中.Orders表不存储顾客的信息,只存储顾客ID.顾客的实际信息存储在Customers
表中.
现在,假如需要列出订购物品"RGAN01"的所有顾客,应该怎样检索?
步骤为下:
1.检索包含物品RGAN01的所有订单的编号.
2.检索具有前一步骤列出的订单编号的所有顾客 的ID
3.检索前一步骤返回的所有顾客ID的顾客信息
方法一:以上每步可以单独作为一个查询来执行.可以把一个SELECT 语句返回的结果用于另外一条SELECT语句的WHERE子句.
方法二:也可以使用子查询把3个查询组合成一条语句
方法三:直接使用内联结来关联两个表直接查询.
方法一实现:



2.方法二实现:

3.方法三实现:

上面是通过 WHERE 语句来实现的,这里面等同于 INNER JOIN...ON (INNER JOIN基本上只用于联结两个表,不太适合多个表联结).
INNER JOIN ...ON 的使用方式

2.自联结
例如:现在要给Jim Jones同一公司的所有顾客发送一封信件.这个查询要求首先找出Jim Jones工作的公司,然后找出在该公司工作的顾客.下面是实现代码:

通过customers表可以看出,cust_contact 里面对应的 Jim Jones 的公司是,Fun4All,然后筛选出 Fun4All 公司的其他联系人和客户ID
以上是通过子查询的方式实现的.
先对对比一下自联结方式实现:

此处要非常小心一定是要c2来进行过滤
3.自然联结
无论何时对表进行联结,应该至少有一列不止出现在一个表中(被联结的列).标准的联结(前一课中介绍的内联结)返回所有数据,相同的列甚至多次出现.
自然联结排除多线出现,使每列只返回一次.
自然联结要求只能选择那些唯一的列,一般通过对一个表使用通配符(SELECT*),而对其他表的列使用明确的子集来完成.如:

在这个例子中,通配符只对第一个表使用,所有其他列明确列出,所以没有重复的列被检索出来.事实上,我们目前所学的每个内联结都是自然联结
4.外联结
许多联结将一个表中的行与另一个表中的行相关联,但有时候需要包含没有关联行的那些行.
例如:
A.对每个顾客下的订单进行计数,包括那些至今尚未下订单的顾客;
B.列出所有产品以及订购数量,包括没有人订购的产品
C.计算平均销售规模,包括那些至今尚未下订单的顾客.
这种联结包含了那些在相关表中没有关联行的行的联结方式就是外联结
例如:

外联结使用的时候,注意区分 LEFT OUTER JOIN 还是 RIGHT OUTER JOIN 就是设定展示哪边的表的所有行.另外还可以使用FULL OUTER JOIN
SQL联结笔记(内联结,自联结,自然联结,外联结区别以及应用)的更多相关文章
- SQL server 使用 内联结(INNER JOIN) 联结多个表 (以及过滤条件 WHERE, AND使用区别)
INNER JOIN ……ON的语法格式: FROM (((表1 INNER JOIN 表2 ON 表1.字段号=表2.字段号) INNER JOIN 表3 ON 表1.字段号=表3.字段号) INN ...
- SQL学习之高级联结(自联结、自然联结、外联接)
create table Customers( Id ,), Company ) null, Name ) null ) insert into Customers values('Fun4All', ...
- SQL 必知必会·笔记<11>创建高级联结
1. 使用表别名 SQL 除了可以对列名和计算字段使用别名,还允许给表名起别名.这样 做有两个主要理由: 缩短SQL 语句: 允许在一条SELECT 语句中多次使用相同的表. 使用表别名示例: SEL ...
- SQL学习笔记
SQL(Structured Query Language)学习笔记 [TOC] Terminal登录数据库 1.登录mysql -u root -p ; 2.显示所有数据库show database ...
- 1.4(SQL学习笔记)分组、子查询、联结、组合查询
一.分组 建表及数据填充语句下载:链接: https://pan.baidu.com/s/1WHYafwqKJEKq1kDwCH_Zlg 提取码: 3wy4 1.1初识分组 分组是按照某一列,将该列中 ...
- ORALCE PL/SQL学习笔记
ORALCE PL/SQL学习笔记 详情见自己电脑的备份数据资料
- 你真的会玩SQL吗?EXISTS和IN之间的区别
你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...
- SQL Server中Text和varchar(max)数据类型区别
SQL Server中Text和varchar(max)数据类型区别 以前只知道text和image是可能被SQL Server淘汰的数据类型,但具体原因不太清楚,今天读书的时候发现了text与v ...
- SQL Server排序函数row_number和rank的区别
SQL Server排序函数row_number和rank的区别 直接看测试结果 declare @table table(name varchar(100),amount int, memo var ...
随机推荐
- 《闲扯Redis九》Redis五种数据类型之Set型
一.前言 Redis 提供了5种数据类型:String(字符串).Hash(哈希).List(列表).Set(集合).Zset(有序集合),理解每种数据类型的特点对于redis的开发和运维非常重要. ...
- PHP is_object() 函数
is_object() 函数用于检测变量是否是一个对象. PHP 版本要求: PHP 4, PHP 5, PHP 7高佣联盟 www.cgewang.com 语法 bool is_object ( m ...
- ABC 162 F Select Half dp 贪心
LINK:Select Half 考试的时候调了一个小时给调自闭了 原来是dp的姿势不太对. 首先 容易发现 奇数最多空2个位置 偶数最多空1一个位置 然后 设f[i][j][k]表示第i个数选了没有 ...
- win10搭建基于docker的odoo开发环境
- 数据量大了一定要分表,分库分表组件Sharding-JDBC入门与项目实战
最近项目中不少表的数据量越来越大,并且导致了一些数据库的性能问题.因此想借助一些分库分表的中间件,实现自动化分库分表实现.调研下来,发现Sharding-JDBC目前成熟度最高并且应用最广的Java分 ...
- 《国际化Web项目测试:记第一次兼职测试的经历(一)》
疫情期间我一直在家远程办公,无意间接到了个做测试兼职的机会.在不耽搁本职工作的情况下,我从今年五月份开启了主职和副职的并行的状态.这种项目经历对于我来说算是一次全新的体验,当然也真是累的够呛.到目前为 ...
- 从零写一个Asp.net core手脚架 (异常处理)
既然是手脚架,那么肯定得明白,手脚架是有限资源的一个整合,我们尽可能完善它,并保留可扩展性才是最终目的,尽可能减少硬编码,让业务不满足的情况下,可以自行修改 我们把解决方案取名Asp.netCoreT ...
- rabbitMQ结合spring-boot使用(1)
从这一节开始我们进入rabbitMQ的实战环节,项目环境是spring-boot 加maven.首先让我们创建一个spring-boot项目,然后引入web依赖和 rabbitMQ的依赖 <de ...
- 无法加载文件或程序集“System.Net.Http,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b03f5f7f11d50a3a”
原因是:System.Net.Http.dll 使用了net4.6的版本的.而System.Net.Http.Formatting.dll使用了4.5的版本. 解决方案:将webconfig文件下的n ...
- Linux学习笔记之ubuntu安装与配置
1.打开虚拟机,点击新建虚拟机 2.安装向导 选择自定义安装 点击包含一个空白的硬盘 选择linux操作系统,版本是ubuntu 设置虚拟机的名称,可以自己写,还有保存的位置也可自选 根据自己电脑性能 ...