- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章几种MySQL中的联接查询操作方法总结由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
前言 。
现在系统的各种业务是如此的复杂,数据都存在数据库中的各种表中,这个主键啊,那个外键啊,而表与表之间就依靠着这些主键和外键联系在一起。而我们进行业务操作时,就需要在多个表之间,使用sql语句建立起关系,然后再进行各种sql操作。那么在使用sql写出各种操作时,如何使用sql语句,将多个表关联在一起,进行业务操作呢?而这篇文章,就对这个知识点进行总结.
联接查询是一种常见的数据库操作,即在两张表(多张表)中进行匹配的操作。MySQL数据库支持如下的联接查询:
在进行各种联接操作时,一定要回忆一下在《SQL逻辑查询语句执行顺序》这篇文章中总结的SQL逻辑查询语句执行的前三步:
每个联接都只发生在两个表之间,即使FROM子句中包含多个表也是如此。每次联接操作也只进行逻辑查询语句的前三步,每次产生一个虚拟表,这个虚拟表再依次与FROM子句的下一个表进行联接,重复上述步骤,直到FROM子句中的表都被处理完为止。 前期准备 。
1.新建一个测试数据库TestDB; 。
。
1
|
create
database
TestDB;
|
创建测试表table1和table2; 。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
CREATE
TABLE
table1
(
customer_id
VARCHAR
(10)
NOT
NULL
,
city
VARCHAR
(10)
NOT
NULL
,
PRIMARY
KEY
(customer_id)
)ENGINE=INNODB
DEFAULT
CHARSET=UTF8;
CREATE
TABLE
table2
(
order_id
INT
NOT
NULL
auto_increment,
customer_id
VARCHAR
(10),
PRIMARY
KEY
(order_id)
)ENGINE=INNODB
DEFAULT
CHARSET=UTF8;
|
插入测试数据; 。
1
2
3
4
5
6
7
8
9
10
11
|
INSERT
INTO
table1(customer_id,city)
VALUES
(
'163'
,
'hangzhou'
);
INSERT
INTO
table1(customer_id,city)
VALUES
(
'9you'
,
'shanghai'
);
INSERT
INTO
table1(customer_id,city)
VALUES
(
'tx'
,
'hangzhou'
);
INSERT
INTO
table1(customer_id,city)
VALUES
(
'baidu'
,
'hangzhou'
);
INSERT
INTO
table2(customer_id)
VALUES
(
'163'
);
INSERT
INTO
table2(customer_id)
VALUES
(
'163'
);
INSERT
INTO
table2(customer_id)
VALUES
(
'9you'
);
INSERT
INTO
table2(customer_id)
VALUES
(
'9you'
);
INSERT
INTO
table2(customer_id)
VALUES
(
'9you'
);
INSERT
INTO
table2(customer_id)
VALUES
(
'tx'
);
|
准备工作做完以后,table1和table2看起来应该像下面这样:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
mysql>
select
*
from
table1;
+
-------------+----------+
| customer_id | city |
+
-------------+----------+
| 163 | hangzhou |
| 9you | shanghai |
| baidu | hangzhou |
| tx | hangzhou |
+
-------------+----------+
4
rows
in
set
(0.00 sec)
mysql>
select
*
from
table2;
+
----------+-------------+
| order_id | customer_id |
+
----------+-------------+
| 1 | 163 |
| 2 | 163 |
| 3 | 9you |
| 4 | 9you |
| 5 | 9you |
| 6 | tx |
+
----------+-------------+
7
rows
in
set
(0.00 sec)
|
准备工作做的差不多了,开始今天的总结吧。 CROSS JOIN联接(交叉联接) 。
CROSS JOIN对两个表执行FROM语句(笛卡尔积)操作,返回两个表中所有列的组合。如果左表有m行数据,右表有n行数据,则执行CROSS JOIN将返回m*n行数据。CROSS JOIN只执行SQL逻辑查询语句执行的前三步中的第一步.
CROSS JOIN可以干什么?由于CROSS JOIN只执行笛卡尔积操作,并不会进行过滤,所以,我们在实际中,可以使用CROSS JOIN生成大量的测试数据.
对上述测试数据,使用以下查询:
1
|
select
*
from
table1
cross
join
table2;
|
就会得到以下结果:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
+
-------------+----------+----------+-------------+
| customer_id | city | order_id | customer_id |
+
-------------+----------+----------+-------------+
| 163 | hangzhou | 1 | 163 |
| 9you | shanghai | 1 | 163 |
| baidu | hangzhou | 1 | 163 |
| tx | hangzhou | 1 | 163 |
| 163 | hangzhou | 2 | 163 |
| 9you | shanghai | 2 | 163 |
| baidu | hangzhou | 2 | 163 |
| tx | hangzhou | 2 | 163 |
| 163 | hangzhou | 3 | 9you |
| 9you | shanghai | 3 | 9you |
| baidu | hangzhou | 3 | 9you |
| tx | hangzhou | 3 | 9you |
| 163 | hangzhou | 4 | 9you |
| 9you | shanghai | 4 | 9you |
| baidu | hangzhou | 4 | 9you |
| tx | hangzhou | 4 | 9you |
| 163 | hangzhou | 5 | 9you |
| 9you | shanghai | 5 | 9you |
| baidu | hangzhou | 5 | 9you |
| tx | hangzhou | 5 | 9you |
| 163 | hangzhou | 6 | tx |
| 9you | shanghai | 6 | tx |
| baidu | hangzhou | 6 | tx |
| tx | hangzhou | 6 | tx |
+
-------------+----------+----------+-------------+
|
INNER JOIN联接(内联接) 。
INNER JOIN比CROSS JOIN强大的一点在于,INNER JOIN可以根据一些过滤条件来匹配表之间的数据。在SQL逻辑查询语句执行的前三步中,INNER JOIN会执行第一步和第二步;即没有第三步,不添加外部行,这是INNER JOIN和接下来要说的OUTER JOIN的最大区别之一.
现在来看看使用INNER JOIN来查询一下:
1
2
3
4
|
select
*
from
table1
inner
join
table2
on
table1.customer_id=table2.customer_id;
|
就会得到以下结果:
1
2
3
4
5
6
7
8
9
10
|
+
-------------+----------+----------+-------------+
| customer_id | city | order_id | customer_id |
+
-------------+----------+----------+-------------+
| 163 | hangzhou | 1 | 163 |
| 163 | hangzhou | 2 | 163 |
| 9you | shanghai | 3 | 9you |
| 9you | shanghai | 4 | 9you |
| 9you | shanghai | 5 | 9you |
| tx | hangzhou | 6 | tx |
+
-------------+----------+----------+-------------+
|
对于INNER JOIN来说,如果没有使用ON条件的过滤,INNER JOIN和CROSS JOIN的效果是一样的。当在ON中设置的过滤条件列具有相同的名称,我们可以使用USING关键字来简写ON的过滤条件,这样可以简化sql语句,例如:
1
|
select
*
from
table1
inner
join
table2 using(customer_id);
|
在实际编写sql语句时,我们都可以省略掉INNER关键字,例如:
1
2
3
4
|
select
*
from
table1
join
table2
on
table1.customer_id=table2.customer_id;
|
但是,请记住,这还是INNER JOIN。 OUTER JOIN联接(外联接) 。
哦,记得有一次参加面试,还问我这个问题来着,那在这里再好好的总结一下。通过OUTER JOIN,我们可以按照一些过滤条件来匹配表之间的数据。OUTER JOIN的结果集等于INNER JOIN的结果集加上外部行;也就是说,在使用OUTER JOIN时,SQL逻辑查询语句执行的前三步,都会执行一遍。关于如何添加外部行,请参考《SQL逻辑查询语句执行顺序》这篇文章中的添加外部行部分内容.
MySQL数据库支持LEFT OUTER JOIN和RIGHT OUTER JOIN,与INNER关键字一样,我们可以省略OUTER关键字。对于OUTER JOIN,同样的也可以使用USING来简化ON子句。所以,对于以下sql语句:
1
2
3
4
|
select
*
from
table1
left
outer
join
table2
on
table1.customer_id=table2.customer_id;
|
我们可以简写成这样:
1
2
3
4
|
select
*
from
table1
left
join
table2
using(customer_id);
|
但是,与INNER JOIN还有一点区别是,对于OUTER JOIN,必须指定ON(或者using)子句,否则MySQL数据库会抛出异常。 NATURAL JOIN联接(自然连接) 。
NATURAL JOIN等同于INNER(OUTER) JOIN与USING的组合,它隐含的作用是将两个表中具有相同名称的列进行匹配。同样的,NATURAL LEFT(RIGHT) JOIN等同于LEFT(RIGHT) JOIN与USING的组合。比如:
1
2
3
4
|
select
*
from
table1
join
table2
using(customer_id);
|
与 。
1
2
3
|
select
*
from
table1
natural
join
table2;
|
等价.
在比如:
1
2
3
4
|
select
*
from
table1
left
join
table2
using(customer_id);
|
与 。
1
2
3
|
select
*
from
table1
natural
left
join
table2;
|
等价。 STRAIGHT_JOIN联接 。
STRAIGHT_JOIN并不是一个新的联接类型,而是用户对sql优化器的控制,其等同于JOIN。通过STRAIGHT_JOIN,MySQL数据库会强制先读取左边的表。举个例子来说,比如以下sql语句:
1
2
3
|
explain
select
*
from
table1
join
table2
on
table1.customer_id=table2.customer_id;
|
它的主要输出部分如下:
1
2
3
4
5
6
|
+
----+-------------+--------+------+---------------+
| id | select_type |
table
| type | possible_keys |
+
----+-------------+--------+------+---------------+
| 1 | SIMPLE | table2 |
ALL
|
NULL
|
| 1 | SIMPLE | table1 |
ALL
|
PRIMARY
|
+
----+-------------+--------+------+---------------+
|
我们可以很清楚的看到,MySQL是先选择的table2表,然后再进行的匹配。如果我们指定STRAIGHT_JOIN方式,例如:
1
2
3
|
explain
select
*
from
table1 straight_join table2
on
table1.customer_id=table2.customer_id;
|
上述语句的主要输出部分如下:
1
2
3
4
5
6
|
+
----+-------------+--------+------+---------------+
| id | select_type |
table
| type | possible_keys |
+
----+-------------+--------+------+---------------+
| 1 | SIMPLE | table1 |
ALL
|
PRIMARY
|
| 1 | SIMPLE | table2 |
ALL
|
NULL
|
+
----+-------------+--------+------+---------------+
|
可以看到,当指定STRAIGHT_JOIN方式以后,MySQL就会先选择table1表,然后再进行的匹配.
那么就有读者问了,这有啥好处呢?性能,还是性能。由于我这里测试数据比较少,大进行大量数据的访问时,我们指定STRAIGHT_JOIN让MySQL先读取左边的表,让MySQL按照我们的意愿来完成联接操作。在进行性能优化时,我们可以考虑使用STRAIGHT_JOIN。 多表联接 。
在上面的所有例子中,我都是使用的两个表之间的联接,而更多时候,我们在工作中,可能不止要联接两张表,可能要涉及到三张或者更多张表的联接查询操作.
对于INNER JOIN的多表联接查询,可以随意安排表的顺序,而不会影响查询的结果。这是因为优化器会自动根据成本评估出访问表的顺序。如果你想指定联接顺序,可以使用上面总结的STRAIGHT_JOIN.
而对于OUTER JOIN的多表联接查询,表的位置不同,涉及到添加外部行的问题,就可能会影响最终的结果。 总结 。
这是MySQL中联接操作的全部内容了,内容虽多,但是都还比较简单,结合文章中的例子,再自己实际操作一遍,完全可以搞定的。这一篇文章就这样了.
最后此篇关于几种MySQL中的联接查询操作方法总结的文章就讲到这里了,如果你想了解更多关于几种MySQL中的联接查询操作方法总结的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我有三张 table 。表 A 有选项名称(即颜色、尺寸)。表 B 有选项值名称(即蓝色、红色、黑色等)。表C通过将选项名称id和选项名称值id放在一起来建立关系。 我的查询需要显示值和选项的名称,而
在mysql中,如何计算一行中的非空单元格?我只想计算某些列之间的单元格,比如第 3-10 列之间的单元格。不是所有的列...同样,仅在该行中。 最佳答案 如果你想这样做,只能在 sql 中使用名称而
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 7 年前。 Improve this ques
我正在为版本7.6进行Elasticsearch查询 我的查询是这样的: { "query": { "bool": { "should": [ {
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 7 年前。 Improve this ques
是否可以编写一个查询来检查任一子查询(而不是一个子查询)是否正确? SELECT * FROM employees e WHERE NOT EXISTS (
我找到了很多关于我的问题的答案,但问题没有解决 我有表格,有数据,例如: Data 1 Data 2 Data 3
以下查询返回错误: 查询: SELECT Id, FirstName, LastName, OwnerId, PersonEmail FROM Account WHERE lower(PersonEm
以下查询返回错误: 查询: SELECT Id, FirstName, LastName, OwnerId, PersonEmail FROM Account WHERE lower(PersonEm
我从 EditText 中获取了 String 值。以及提交查询的按钮。 String sql=editQuery.getText().toString();// SELECT * FROM empl
我有一个或多或少有效的查询(关于结果),但处理大约需要 45 秒。这对于在 GUI 中呈现数据来说肯定太长了。 所以我的需求是找到一个更快/更高效的查询(几毫秒左右会很好)我的数据表大约有 3000
这是我第一次使用 Stack Overflow,所以我希望我以正确的方式提出这个问题。 我有 2 个 SQL 查询,我正在尝试比较和识别缺失值,尽管我无法将 NULL 字段添加到第二个查询中以识别缺失
什么是动态 SQL 查询?何时需要使用动态 SQL 查询?我使用的是 SQL Server 2005。 最佳答案 这里有几篇文章: Introduction to Dynamic SQL Dynami
include "mysql.php"; $query= "SELECT ID,name,displayname,established,summary,searchlink,im
我有一个查询要“转换”为 mysql。这是查询: select top 5 * from (select id, firstName, lastName, sum(fileSize) as To
通过我的研究,我发现至少从 EF 4.1 开始,EF 查询上的 .ToString() 方法将返回要运行的 SQL。事实上,这对我来说非常有用,使用 Entity Framework 5 和 6。 但
我在构造查询来执行以下操作时遇到问题: 按activity_type_id过滤联系人,仅显示最近事件具有所需activity_type_id或为NULL(无事件)的联系人 表格结构如下: 一个联系人可
如何让我输入数据库的信息在输入数据 5 分钟后自行更新? 假设我有一张 table : +--+--+-----+ |id|ip|count| +--+--+-----+ |
我正在尝试搜索正好是 4 位数字的 ID,我知道我需要使用 LENGTH() 字符串函数,但找不到如何使用它的示例。我正在尝试以下(和其他变体)但它们不起作用。 SELECT max(car_id)
我有一个在 mysql 上运行良好的 sql 查询(查询 + 连接): select sum(pa.price) from user u , purchase pu , pack pa where (
我是一名优秀的程序员,十分优秀!