SQL中Join的使用示例

46次阅读
没有评论

共计 4095 个字符,预计需要花费 11 分钟才能阅读完成。

自动写代码机器人,免费开通

这篇文章主要介绍了 SQL 中 Join 的使用示例,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让丸趣 TV 小编带着大家一起了解一下。

一. 基本概念

关于 sql 语句中的连接(join)关键字,是较为常用而又不太容易理解的关键字,下面这个例子给出了一个简单的解释 –建表 user1,user2:

table1 : create table user2(id int, user_name varchar(10), over varchar(10));
insert into user1 values(1,‘tangseng ,‘dtgdf
insert into user1 values(2,‘sunwukong ,‘dzsf
insert into user1 values(1,‘zhubajie ,‘jtsz
insert into user1 values(1,‘shaseng ,‘jslh
table2 : create table user2(id int, user_name varchar(10), over varchar(10));
insert into user2 values(1,‘sunwukong ,‘chengfo
insert into user2 values(2,‘niumowang ,‘chengyao
insert into user2 values(3,‘jiaomowang ,‘chengyao
insert into user2 values(4,‘pengmowang ,‘chengyao

SQL 标准中 Join 的类型

SQL 中 Join 的使用示例

1. 内连接(inner join 或 join)

(1). 概念:内联接是基于连接谓词将两张表的列结合在一起,产生新的结果表

(2). 内连接维恩图:

SQL 中 Join 的使用示例

(3).sql 语句

select a.id, a.user_name, b.over from user1 a inner join user2 b on a.user_name=b.user_name;

结果:

SQL 中 Join 的使用示例

2. 外连接

外连接包括左向外联接、右向外联接或完整外部联接

a. 左外连接:left join 或 left outer join
(1)概念:左向外联接的结果集包括 LEFT OUTER 子句中指定的左表的所有行,而不仅仅是联接列所匹配的行。如果左表的某行在右表中没有匹配行,则在相关联的结果集行中右表的所有选择列表列均为空值(null)。

(2)左外连接维恩图:

SQL 中 Join 的使用示例

(3)sql 语句:

select a.id, a.user_name, b.over from user1 a left join user2 b on a.user_name=b.user_name;

结果:

SQL 中 Join 的使用示例

b. 右外连接:right join 或 right outer join
(1)右向外联接是左向外联接的反向联接。将返回右表的所有行。如果右表的某行在左表中没有匹配行,则将为左表返回空值。
(2)右外连接维恩图:

SQL 中 Join 的使用示例

(3)sql 语句

select b.user_name, b.over, a.over from user1 a right join user2 b on a.user_name=b.user_name;

结果:

SQL 中 Join 的使用示例

c. 全外连接:full join 或 full outer join

(1)完整外部联接返回左表和右表中的所有行。当某行在另一个表中没有匹配行时,则另一个表的选择列表列包含空值。如果表之间有匹配行,则整个结果集行包含基表的数据值。
(2)右外连接维恩图:

SQL 中 Join 的使用示例

(3)sql 语句

select a.id, a.user_name, b.over from user1 a full join user2 b on a.user_name=b.user_name

在 mysql 中查询全连接会报 1064 的错误,mysql 不支持全连接查询,代替语句:

select a.user_name,a.over,b.over from user1 a left join user2 b on a.user_name = b.user_name union all select b.user_name,b.over ,a.over from user1 a right join user2 b on a.user_name = b.user_name;

结果:

SQL 中 Join 的使用示例

3. 笛卡尔连接(交叉连接)

1. 概念:没有 WHERE 子句的交叉联接将产生联接所涉及的表的笛卡尔积。第一个表的行数乘以第二个表的行数等于笛卡尔积结果集的大小。(user1 和 user2 交叉连接产生 4 *4=16 条记录)
2. 交叉连接:cross join (不带条件 on)
3.sql 语句:
select a.user_name,b.user_name, a.over, b.over from user1 a cross join user2 b;

二. 使用技巧

1. 使用 join 更新表
我们使用下面语句将 user1 表中同时存在 user1 表和 user2 表中记录的 over 字段更新为‘qtda。

update user1 set over= qtds where user1.user_name in (select b.user_name from user1 a inner join user2 b on a.user_name = b.user_name);

这条语句在 sql server, oracle 中都可以正确执行,在 mysql 却报错,mysql 不支持更新子查询的表,那么我们使用下面语句可以在做到。

update user1 a join (select b.user_name from user1 a join user2 b on a.user_name = b.user_name) b on a.user_name = b.user_name set a.over =‘qtds

2. 使用 join 优化子查询

子查询效率比较低效,使用下面语句进行查询
select a.user_name, a.over,(select over from user2 b where a.user_name=b.user_name) as over2 from user1 a;
使用 join 优化子查询,可以实现同样的效果
select a.user_name, a.over, b.over as over2 from user1 a left join user2
b on a.user_name = b.user_name;

3. 使用 join 优化聚合子查询

引入一张新表:user_kills
create table user_kills(user_id int, timestr varchar(20), kills int(10));
insert into user_kills values(2,‘2015-5-12 , 20);
insert into user_kills values(2,‘2015-5-15 , 18);
insert into user_kills values(3,‘2015-5-11 , 16);
insert into user_kills values(3,‘2015-5-14 , 13);
insert into user_kills values(3,‘2015-5-16 , 17);
insert into user_kills values(4,‘2015-5-12 , 16);
insert into user_kills values(4,‘2015-5-10 , 13);

查询 user1 中每人对应 user_kills 表中 kills 最大的日期,使用聚合子查询语句:

select a.user_name,b.timestr, b.kills from user1 a join user_kills b on a
.id = b.user_id where b.kills = (select MAX(c.kills) from user_kills c where c.user_id = b.user_id);

使用 join 优化聚合子查询(避免子查询)

select a.user_name, b.timestr, b.kills from user1 a join user_kills b on
a.id = b.user_id join user_kills c on c.user_id = b.user_id group by a.user_name, b.timestr, b.kills having b.kills = max(c.kills);

结果:

SQL 中 Join 的使用示例

4. 实现分组选择数据

要求查询出 user1 中每个人 kills 对多的前两天。
首先,我们可以通过下面语句查询出某个人 kills 最多的两天;

select a.user_name, b.timestr, b.kills from user1 a join user_kills b on
a.id = b.user_id where a.user_name = sunwukong order by b.kills desc limit 2;

那么如何通过一个语句查询出所有人 kills 最多的两天的呢?看下面的语句:

WITH tmp AS (select a.user_name, b.timestr, b.kills, ROW_NUMBER() over(partition by a.user_name order by b.kills) cnt from user1 a join user_kills b on a.id = b.user_id) select * from tmp where cnt

上面的语句在 sql server 和 oracle 都是支持的,但是 mysql 不支持分组排序函数 ROW_NUMBER(), 下面提供一种替代方法:

select d.user_name,c.timestr, kills from (select user_id, timestr, kills, (select count(*) from user_kills b where b.user_id = a.user_id and a.kills = b.kills) as cnt from user_kills a group by user_id, timestr, kills) c join user1 d on c.user_id = d.id where cnt

结果:

SQL 中 Join 的使用示例

感谢你能够认真阅读完这篇文章,希望丸趣 TV 小编分享的“SQL 中 Join 的使用示例”这篇文章对大家有帮助,同时也希望大家多多支持丸趣 TV,关注丸趣 TV 行业资讯频道,更多相关知识等着你来学习!

向 AI 问一下细节

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-12-04发表,共计4095字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)