SQL内连接与外连接用法与区别
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQL内连接与外连接用法与区别相关的知识,希望对你有一定的参考价值。
参考技术A1、内连接:从结果表中删除与其他被连接表中没有匹配行的所有行。
2、外连接:返回每个满足第一个(顶端)输入与第二个(底端)输入的联接的行。
二、语法不同
1、内连接:select fieldlist from table1 [inner] join table2 on table1.column=table2.column
2、外连接:select * from dave a full join bl b on a .id = b .id;
三、注意事项不同
1、内连接:需要区分在嵌套查询中使用的any与all的区别,any相当于逻辑运算“||”而all则相当于逻辑运算“&&”
2、外连接:左表和右表都不做限制,所有的记录都显示,两表不足的地方用null 填充。 全外连接不支持(+)这种写法。
参考资料来源:百度百科-外连接
参考资料来源:百度百科-内连接
内连接与外连接-及其典型案例
在数据库系统中,join用于比较和组合(字面意思是连接)并从数据库中的两个或多个表返回特定数据行。内连接从表中查找并返回匹配数据,而外连接从表中查找并返回匹配数据和一些不同的数据。
内连接
内连接侧重于两个表之间的共性。使用内部联接时,要比较的两个(或多个)表之间,必须有一些匹配数据,即链接的条件。内部联接在表中搜索匹配或重叠的数据。找到后,内连接将信息合并并返回到一个新表中。
SELECT 字段列表
FROM A表 INNER JOIN B表
ON 关联条件
WHERE 等其他子句;
内连接例子
让我们考虑两个表的常见场景:产品价格和数量。两个表中的公共信息是产品名称,因此这是连接表的逻辑列。有一些产品在两个表中是通用的;其他的对于其中一个表是唯一的,并且在另一个表中没有匹配项。
下面是通过产品名称作为连接条件,将符合条件的信息返回
外连接
外连接返回一组记录(或行),其中包括内连接将返回的内容,但也包括在其他表中找不到对应匹配项的其他行。
外连接分为三种类型:
- 左外连接(或左连接)
- 右外连接(或右连接)
- 完全外连接(或完全连接)
这些外部联接中的每一个都指的是正在比较、组合和返回的数据部分。有时在此过程中会产生null,因为某些数据是共享的,而其他数据则不是。
左连接
左外连接将返回表 1中的所有数据和所有共享数据,但仅返回表 2 中的相应数据,即左连接。
SELECT 字段列表
FROM A表 LEFT JOIN B表
ON 关联条件
WHERE 等其他子句;
左连接例子
在我们的示例数据库中,“左边”(prices表)有两种产品——oranges和 tomatoes ,在“右边”(quantities表)上没有相应的条目。在左连接中,这些行包含在结果集中,数量列中为 NULL。结果中的其他行与内部联接相同。
右连接
右外连接返回表 2 的数据和所有共享数据,但仅返回表 1 中的相应数据,即右连接。
SELECT 字段列表
FROM A表 RIGHT JOIN B表
ON 关联条件
WHERE 等其他子句;
右连接例子
与左连接示例类似,右外连接的输出包括内连接的所有行和来自“右”(quantities表)的两行 - broccoli 和squash - 在左侧没有匹配的条目。
全连接
流行的 MySQL 数据库管理系统不支持的完全外连接或完全连接,无论是否存在共享信息,都会合并并返回来自两个或多个表的所有数据。将完全连接视为简单地复制所有指定信息,但在一个表中,而不是在多个表中。在缺少匹配数据的情况下,将产生空值。
SELECT 字段列表
FROM A表 FULL JOIN B表
ON 关联条件
WHERE 等其他子句;
这些只是基础知识,但很多事情都可以通过连接来完成。甚至还有可以排除其他连接的连接!
多表连接问题
用户信息表:user_profile
id | device_id | gender | age | university | gpa | active_days_within_30 | question_cnt | answer_cnt |
1 | 2138 | male | 21 | 北京大学 | 3.4 | 7 | 2 | 12 |
2 | 3214 | male | NULL | 复旦大学 | 4 | 15 | 5 | 25 |
3 | 6543 | female | 20 | 北京大学 | 3.2 | 12 | 3 | 30 |
4 | 2315 | female | 23 | 浙江大学 | 3.6 | 5 | 1 | 2 |
5 | 5432 | male | 25 | 山东大学 | 3.8 | 20 | 15 | 70 |
6 | 2131 | male | 28 | 山东大学 | 3.3 | 15 | 7 | 13 |
7 | 4321 | male | 28 | 复旦大学 | 3.6 | 9 | 6 | 52 |
第一行表示:id为1的用户的常用信息为使用的设备id为2138,性别为男,年龄21岁,北京大学,gpa为3.4,在过去的30天里面活跃了7天,发帖数量为2,回答数量为12
最后一行表示:id为7的用户的常用信息为使用的设备id为432,性别为男,年龄28岁,复旦大学,gpa为3.6,在过去的30天里面活跃了9天,发帖数量为6,回答数量为52
题库练习明细表:question_practice_detail
id | device_id | question_id | result |
1 | 2138 | 111 | wrong |
2 | 3214 | 112 | wrong |
3 | 3214 | 113 | wrong |
4 | 6534 | 111 | right |
5 | 2315 | 115 | right |
6 | 2315 | 116 | right |
7 | 2315 | 117 | wrong |
8 | 5432 | 117 | wrong |
9 | 5432 | 112 | wrong |
10 | 2131 | 113 | right |
11 | 5432 | 113 | wrong |
12 | 2315 | 115 | right |
13 | 2315 | 116 | right |
14 | 2315 | 117 | wrong |
15 | 5432 | 117 | wrong |
16 | 5432 | 112 | wrong |
17 | 2131 | 113 | right |
18 | 5432 | 113 | wrong |
19 | 2315 | 117 | wrong |
20 | 5432 | 117 | wrong |
21 | 5432 | 112 | wrong |
22 | 2131 | 113 | right |
23 | 5432 | 113 | wrong |
第一行表示:id为1的用户的常用信息为使用的设备id为2138,在question_id为111的题目上,回答错误
......
最后一行表示:id为23的用户的常用信息为使用的设备id为5432,在question_id为113的题目上,回答错误
表:question_detail
id | question_id | difficult_level |
1 | 111 | hard |
2 | 112 | medium |
3 | 113 | easy |
4 | 115 | easy |
5 | 116 | medium |
6 | 117 | easy |
第一行表示: 题目id为111的难度为hard
....
第一行表示: 题目id为117的难度为easy
SQL23 统计每个学校各难度的用户平均刷题数
请你写一个SQL查询,计算不同学校、不同难度的用户平均答题量,根据示例,你的查询应返回以下结果(结果在小数点位数保留4位,4位之后四舍五入):
university | difficult_level | avg_answer_cnt |
北京大学 | hard | 1.0000 |
复旦大学 | easy | 1.0000 |
复旦大学 | medium | 1.0000 |
山东大学 | easy | 4.5000 |
山东大学 | medium | 3.0000 |
浙江大学 | easy | 5.0000 |
浙江大学 | medium | 2.0000 |
解释:
第一行:北京大学有设备id为2138,6543这2个用户,这2个用户在question_practice_detail表下都只有一条答题记录,且答题题目是111,从question_detail可以知道这个题目是hard,故 北京大学的用户答题为hard的题目平均答题为2/2=1.0000
第二行,第三行:复旦大学有设备id为3214,4321这2个用户,但是在question_practice_detail表只有1个用户(device_id=3214有答题,device_id=4321没有答题,不计入后续计算)有2条答题记录,且答题题目是112,113各1个,从question_detail可以知道题目难度分别是medium和easy,故 复旦大学的用户答题为easy, medium的题目平均答题量都为1(easy=1或medium=1) /1 (device_id=3214)=1.0000
第四行,第五行:山东大学有设备id为5432和2131这2个用户,这2个用户总共在question_practice_detail表下有12条答题记录,且答题题目是112,113,117,且数目分别为3,6,3,从question_detail可以知道题目难度分别为medium,easy,easy,所以,easy共有9个,故easy的题目平均答题量= 9(easy=9)/2 (device_id=3214 or device_id=5432) =4.5000,medium共有3个,medium的答题只有device_id=5432的用户,故medium的题目平均答题量= 3(medium=9)/1 ( device_id=5432) =3.0000
.....
SQL24 统计每个用户的平均刷题数
题目:运营想要查看参加了答题的山东大学的用户在不同难度下的平均答题题目数,请取出相应数据
请你写一个SQL查询,计算山东、不同难度的用户平均答题量,根据示例,你的查询应返回以下结果(结果在小数点位数保留4位,4位之后四舍五入):
university | difficult_level | avg_answer_cnt |
山东大学 | easy | 4.5000 |
山东大学 | medium | 3.0000 |
山东大学有设备id为5432和2131这2个用户,这2个用户总共在question_practice_detail表下有12条答题记录,且答题题目是112,113,117,且数目分别为3,6,3,从question_detail可以知道题目难度分别为medium,easy,easy,所以,easy共有9个,故easy的题目平均答题量= 9(easy=9)/2 (device_id=3214 or device_id=5432) =4.5000,medium共有3个,medium的答题只有device_id=5432的用户,故medium的题目平均答题量= 3(medium=9)/1 ( device_id=5432) =3.0000
--题目:运营想要计算一些参加了答题的不同学校、不同难度的用户平均答题量,请你写SQL取出相应数据
-----左连接
select UNIVERSITY,DIFFICULT_LEVEL,ROUND(COUNT(QPD.QUESTION_ID) / COUNT(distinct QPD.DEVICE_ID), 4) as AVG_ANSWER_CNT
from QUESTION_PRACTICE_DETAIL QPD left join USER_PROFILE UP on UP.DEVICE_ID=QPD.DEVICE_ID
left join question_detail qd ON qd.question_id=qpd.question_id
group by UNIVERSITY, DIFFICULT_LEVEL;
----另一种写法,内连接
select UNIVERSITY , DIFFICULT_LEVEL , ROUND(COUNT(QPD.QUESTION_ID)/COUNT(distinct QPD.DEVICE_ID),4) AVG_ANSWER_CNT ----根据分组计算的结果结算用户平均答题量
from USER_PROFILE UP
inner join QUESTION_PRACTICE_DETAIL QPD on UP.DEVICE_ID = QPD.DEVICE_ID
inner join QUESTION_DETAIL QD on QPD.QUESTION_ID = QD.QUESTION_ID --三个表中查询数据
group by UNIVERSITY , DIFFICULT_LEVEL; --计算不同学校、不同难度
-----等值连接
select UNIVERSITY , DIFFICULT_LEVEL , round(COUNT(QPD.QUESTION_ID)/COUNT(distinct QPD.DEVICE_ID),4) AVG_ANSWER_CNT ----根据分组计算的结果结算用户平均答题量
from USER_PROFILE UP , QUESTION_PRACTICE_DETAIL QPD , QUESTION_DETAIL QD --三个表中查询数据
where UP.DEVICE_ID = QPD.DEVICE_ID and QPD.QUESTION_ID = QD.QUESTION_ID --建立内连接
group by UNIVERSITY , DIFFICULT_LEVEL; --计算不同学校、不同难度
--测试
SELECT *
from USER_PROFILE UP , QUESTION_PRACTICE_DETAIL QPD, QUESTION_DETAIL QD
WHERE up.device_id = qpd.device_id AND qpd.question_id = qd.question_id;
----题目:运营想要查看参加了答题的山东大学的用户在不同难度下的平均答题题目数,请取出相应数据
select UNIVERSITY , DIFFICULT_LEVEL , COUNT(QPD.QUESTION_ID)/COUNT(distinct QPD.DEVICE_ID) AVG_ANSWER_CNT
from USER_PROFILE UP , QUESTION_PRACTICE_DETAIL QPD , QUESTION_DETAIL QD
where UP.DEVICE_ID = QPD.DEVICE_ID and QPD.QUESTION_ID = QD.QUESTION_ID
group by UNIVERSITY,DIFFICULT_LEVEL
having UNIVERSITY='山东大学';
--------------创建实验表
drop table user_profile;
DROP TABLE question_practice_detail;
drop table question_detail;
CREATE TABLE user_profile (
id int NOT NULL,
device_id int NOT NULL,
gender varchar(14) NOT NULL,
age int ,
university varchar(32) NOT NULL,
gpa float,
active_days_within_30 int ,
question_cnt int ,
answer_cnt int
);
CREATE TABLE question_practice_detail (
id int NOT NULL,
device_id INT NOT NULL,
question_id int NOT NULL,
result varchar(32) NOT NULL
);
CREATE TABLE question_detail (
ID INT NOT NULL,
question_id int NOT NULL,
difficult_level varchar(32) NOT NULL
);
SELECT * FROM question_practice_detail; --题库练习明细表
SELECT * FROM question_detail; --
SELECT * FROM user_profile; --用户信息表
INSERT INTO user_profile VALUES(1,2138,'male',21,'北京大学',3.4,7,2,12);
INSERT INTO user_profile VALUES(2,3214,'male',null,'复旦大学',4.0,15,5,25);
INSERT INTO user_profile VALUES(3,6543,'female',20,'北京大学',3.2,12,3,30);
INSERT INTO user_profile VALUES(4,2315,'female',23,'浙江大学',3.6,5,1,2);
INSERT INTO user_profile VALUES(5,5432,'male',25,'山东大学',3.8,20,15,70);
INSERT INTO user_profile VALUES(6,2131,'male',28,'山东大学',3.3,15,7,13);
INSERT INTO user_profile VALUES(7,4321,'male',28,'复旦大学',3.6,9,6,52);
INSERT INTO question_practice_detail VALUES(1,2138,111,'wrong');
INSERT INTO question_practice_detail VALUES(2,3214,112,'wrong');
INSERT INTO question_practice_detail VALUES(3,3214,113,'wrong');
INSERT INTO question_practice_detail VALUES(4,6543,111,'right');
INSERT INTO question_practice_detail VALUES(5,2315,115,'right');
INSERT INTO question_practice_detail VALUES(6,2315,116,'right');
INSERT INTO question_practice_detail VALUES(7,2315,117,'wrong');
INSERT INTO question_practice_detail VALUES(8,5432,117,'wrong');
INSERT INTO question_practice_detail VALUES(9,5432,112,'wrong');
INSERT INTO question_practice_detail VALUES(10,2131,113,'right');
INSERT INTO question_practice_detail VALUES(11,5432,113,'wrong');
INSERT INTO question_practice_detail VALUES(12,2315,115,'right');
INSERT INTO question_practice_detail VALUES(13,2315,116,'right');
INSERT INTO question_practice_detail VALUES(14,2315,117,'wrong');
INSERT INTO question_practice_detail VALUES(15,5432,117,'wrong');
INSERT INTO question_practice_detail VALUES(16,5432,112,'wrong');
INSERT INTO question_practice_detail VALUES(17,2131,113,'right');
INSERT INTO question_practice_detail VALUES(18,5432,113,'wrong');
INSERT INTO question_practice_detail VALUES(19,2315,117,'wrong');
INSERT INTO question_practice_detail VALUES(20,5432,117,'wrong');
INSERT INTO question_practice_detail VALUES(21,5432,112,'wrong');
INSERT INTO question_practice_detail VALUES(22,2131,113,'right');
INSERT INTO question_practice_detail VALUES(23,5432,113,'wrong');
INSERT INTO question_detail VALUES(1,111,'hard');
INSERT INTO question_detail VALUES(2,112,'medium');
INSERT INTO question_detail VALUES(3,113,'easy');
INSERT INTO question_detail VALUES(4,115,'easy');
INSERT INTO question_detail VALUES(5,116,'medium');
INSERT INTO question_detail VALUES(6,117,'easy');
对查询结果进行组合
SQL25 查找山东大学或者性别为男生的信息
题目:现在运营想要分别查看学校为山东大学或者性别为男性的用户的device_id、gender、age和gpa数据,请取出相应结果,结果不去重。
示例:user_profile
id | device_id | gender | age | university | gpa | active_days_within_30 | question_cnt | answer_cnt |
1 | 2138 | male | 21 | 北京大学 | 3.4 | 7 | 2 | 12 |
2 | 3214 | male | 复旦大学 | 4 | 15 | 5 | 25 | |
3 | 6543 | female | 20 | 北京大学 | 3.2 | 12 | 3 | 30 |
4 | 2315 | female | 23 | 浙江大学 | 3.6 | 5 | 1 | 2 |
5 | 5432 | male | 25 | 山东大学 | 3.8 | 20 | 15 | 70 |
6 | 2131 | male | 28 | 山东大学 | 3.3 | 15 | 7 | 13 |
7 | 4321 | male | 26 | 复旦大学 | 3.6 | 9 | 6 | 52 |
根据示例,你的查询应返回以下结果(注意输出的顺序,先输出学校为山东大学再输出性别为男生的信息):
device_id | gender | age | gpa |
5432 | male | 25 | 3.8 |
2131 | male | 28 | 3.3 |
2138 | male | 21 | 3.4 |
3214 | male | None | 4 |
5432 | male | 25 | 3.8 |
2131 | male | 28 | 3.3 |
4321 | male | 28 | 3.6 |
select device_id , gender , age , gpa from user_profile where university = '山东大学'
UNION --去重
select device_id , gender , age , gpa from user_profile where gender = 'male'
select device_id , gender , age , gpa from user_profile where university = '山东大学'
UNION ALL --不去重,这是正确答案
select device_id , gender , age , gpa from user_profile where gender = 'male'
以上是关于SQL内连接与外连接用法与区别的主要内容,如果未能解决你的问题,请参考以下文章