一.基本概念

关于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的类型

1. 内连接(inner join或join)

(1).概念:内联接是基于连接谓词将两张表的列结合在一起,产生新的结果表
(2).内连接维恩图:
(3).sql语句
select a.id, a.user_name, b.over from user1 a inner join user2 b on a.user_name=b.user_name;
结果:

2. 外连接

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

a.左外连接:left join 或 left outer join

(1)概念:左向外联接的结果集包括 LEFT OUTER 子句中指定的左表的所有行,而不仅仅是联接列所匹配的行。如果左表的某行在右表中没有匹配行,则在相关联的结果集行中右表的所有选择列表列均为空值(null)。
(2)左外连接维恩图:
(3)sql语句:
select a.id, a.user_name, b.over from user1 a left join user2 b on a.user
_name=b.user_name;
结果:

b.右外连接:right join 或 right outer join

(1)右向外联接是左向外联接的反向联接。将返回右表的所有行。如果右表的某行在左表中没有匹配行,则将为左表返回空值。
(2)右外连接维恩图:
(3)sql语句
select b.user_name, b.over, a.over from user1 a right join user2 b on a.user_name=b.user_name;
结果:

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

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

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);
结果:

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 <= 2;
上面的语句在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 <= 2;
结果:

SQL之Join的使用的更多相关文章

  1. 图解SQL的Join 转自coolshell

    对于SQL的Join,在学习起来可能是比较乱的.我们知道,SQL的Join语法有很多inner的,有outer的,有left的,有时候,对于Select出来的结果集是什么样子有点不是很清楚.Codin ...

  2. 图解SQL的Join(转)

    对于SQL的Join,在学习起来可能是比较乱的.我们知道,SQL的Join语法有很多inner的,有outer的,有left的,有时候,对于Select出来的结果集是什么样子有点不是很清楚.Codin ...

  3. SQL JOIN\SQL INNER JOIN 关键字\SQL LEFT JOIN 关键字\SQL RIGHT JOIN 关键字\SQL FULL JOIN 关键字

    SQL join 用于根据两个或多个表中的列之间的关系,从这些表中查询数据. Join 和 Key 有时为了得到完整的结果,我们需要从两个或更多的表中获取结果.我们就需要执行 join. 数据库中的表 ...

  4. 关于sql中join

    对于SQL的Join,在学习起来可能是比较乱的.我们知道,SQL的Join语法有很多inner的,有outer的,有left的,有时候,对于Select出来的结果集是什么样子有点不是很清楚.Codin ...

  5. 图解SQL的Join(转摘)

    转摘网址:http://coolshell.cn/articles/3463.html 对于SQL的Join,在学习起来可能是比较乱的.我们知道,SQL的Join语法有很多inner的,有outer的 ...

  6. SQL RIGHT JOIN 关键字

    SQL RIGHT JOIN 关键字 RIGHT JOIN 关键字会右表 (table_name2) 那里返回所有的行,即使在左表 (table_name1) 中没有匹配的行. RIGHT JOIN ...

  7. SQL LEFT JOIN 关键字

    SQL LEFT JOIN 关键字 LEFT JOIN 关键字会从左表 (table_name1) 那里返回所有的行,即使在右表 (table_name2) 中没有匹配的行. LEFT JOIN 关键 ...

  8. SQL 连接 JOIN 例解。(左连接,右连接,全连接,内连接,交叉连接,自连接)

    SQL 连接 JOIN 例解.(左连接,右连接,全连接,内连接,交叉连接,自连接) 最近公司在招人,同事问了几个自认为数据库可以的应聘者关于库连接的问题,回答不尽理想-现在在这写写关于它们的作用假设有 ...

  9. SQL Server Join方式

    原文:SQL Server Join方式 0.参考文献 Microsoft SQL Server企业级平台管理实践 看懂SqlServer查询计划 1.测试数据准备 参考:Sql Server中的表访 ...

  10. SQL的JOIN语法解析(inner join, left join, right join, full outer join的区别)

    原文链接:http://www.powerxing.com/sql-join/ 总的来说,四种JOIN的使用/区别可以描述为: left join 会从左表(shop)那里返回所有的记录,即使在右表( ...

随机推荐

  1. Onvif鉴权实现方式

    Onvif鉴权实现方式 Digest = B64ENCODE( SHA1( B64DECODE( Nonce ) + Date + Password ) ) gsoap中digest生成代码: int ...

  2. 使用select处理任意数目个客户的单进程程序

    改写http://www.cnblogs.com/nufangrensheng/p/3587962.html中的TCP回射服务器程序,把它重写成使用select来处理任意数目个客户的单进程程序,而不是 ...

  3. Spring事务属性具体解释

    Spring.是一个Java开源框架,是为了解决企业应用程序开发复杂性由Rod Johnson创建的.框架的主要优势之中的一个就是其分层架构,分层架构同意使用者选择使用哪一个组件,同一时候为 J2EE ...

  4. UISearchbar去除背景色的方法,适合iOS5/6/7/8.0beta

    通常使用UISearchbar都须要去除其背景色来与自己的界面风格保持协调,可是UISearchbar的设计随着iOS版本号的升级不断地在发生着变化.以下我们通过分析UISearchbar在各个iOS ...

  5. jquery prop('checked', true)解决attr('checked', true)不能选中radio问题

    正如标题所言,使用:prop('checked', true)就可以了

  6. apache绑定多个域名

    在httpd.conf里, 1.把#NameVirtualHost *:80前的注释去掉2.ServerName 127.0.0.1 修改成ServerName 72.167.11.303.#Name ...

  7. 14条最佳JS代码编写技巧

    http://gaohaixian.blog.163.com/blog/static/123260105201142645458315/写任何编程代码,不同的开发者都会有不同的见解.但参考一下总是好的 ...

  8. idea 更换编辑器背景图片

    插件名称是:BackgroundImage, 安装后效果图

  9. 详解 boost 库智能指针(scoped_ptr<T> 、shared_ptr<T> 、weak_ptr<T> 源码分析)

    一.boost 智能指针 智能指针是利用RAII(Resource Acquisition Is Initialization:资源获取即初始化)来管理资源.关于RAII的讨论可以参考前面的文章.在使 ...

  10. Java SSL证书的安装

    https正在成为主流,http估计在不久的将来会被彻底放弃…… 一个Java程序需要访问一个https的网站的时候,可能需要涉及证书的安装,卸载等操作. 一.证书的下载 打开浏览器输入https:/ ...