理解mysql执行多表联合查询
阅读目录
- 一:inner join(内连接)
- 二:left join(左连接)
- 三:right join(右连接)
- 四:cross join(交叉连接)
- 五:union操作
- 六:node+mysql 多表联合查询
查询多张表一般有如下连接方法:
1)内连接:join, inner join
2)外连接:left join, left outer join, right join, right outer join, union;
3) 交叉连接:cross join
join的含义是:用于多表中字段直接的联系。
基本语法如下:
select * from table1 inner|left|right join table2 on conditiona
说明:table1 是指第一张表。table2是指第二张表。 on 后面的含义是:满足这个条件。
join按照功能可以分成如下三类:
1) inner join(内连接,或叫等值连接):取得两个表中存在连接匹配关系的记录。
2)left join(左连接):取得左表(table1)完全记录,右表(table2)如果有条件相符合的记录就匹配,否则为null;
3) right join(右连接): 取得右表(table2)完全记录,左表(table1)如果有条件相符合的记录就匹配,否则为null;
我们来看一个列子:
如下是user1表和user2表中的数据如下所示:
一:inner join(内连接)
基本语法如下:
select * from user inner join user2 on user.age = user2.age;
如上代码的含义是:查询user表和user2表(内连接) 通过on后面的条件查询,user表中的age字段 等于 user2表中的age这个条件满足的话,才会把两个表中的数据都查询出来的,否则的话,查询数据就是空哦。如下所示:
二:left join(左连接)
基本语法如下:
select * from user left join user2 on user.age = user2.age;
如上代码的含义是:如果user表中的age字段值 等于 user2表中的age字段的值的话,那么就会把所有的数据都查询出来,如果该表中的字段age值不相等的话,那么user表中的记录会全部查询出来,user2表中的所有字段为null值。
如下所示:
三:right join(右连接)
基本语法如下:
select * from user right join user2 on user.age = user2.age;
和上面的 left join 的含义相反,就是说 如果条件相等的话,就会把两张表的数据都查询出来,如果不相等的话,就会把第二张表的数据查询出来,第一张表的数据字段值为null.
如下所示:
四:cross join(交叉连接)
交叉连接,得到的结果是两个表的乘积; 效果和 inner join 类似,如下所示:
五:union操作
select * from user left join user2 on user.username = user2.username union select * from user right join user2 on user.username = user2.username;
上面代码的含义是:查询user表和user2表,如果该两张表的username值相等的话,使用left join(左链接) 和 right join(右连接),如果都相等的话,就把两张表所有的数据查询出来。否则的话,两张表字段不相等的话,那么第一个条件 left join查询后的数据就是 按照user表查询出所有的数据,user2表中的数据字段值为null;union的含义的意思可以理解为或者的意思,我们可以理解它为or的意思,第二个条件是使用 right join 连接符,意思是如果username字段不相等的话,就按照第二张表的数据全部查询出来,第一张表的所有字段查询值为null。如下所示:
六:node+mysql 多表联合查询
在mysql模块中,我们可以使用Connection对象的query方法的第一个参数编写sql语句来执行多表联合查询,但是如果在sql语句中指定了相同的字段(比如相同的字段在不同的表中),那么在默认的情况下,后面的字段会覆盖前面的字段查询出来的数据。从而不是我们想要的结果。我们是想要把这两张表的数据同时查询出来。为了演示下,我们新建两张表,一张是user表,该表有4个字段,分别是id,username, password, age; 另外一张表是user2表,该表有四个字段,分别是id,username,password,age等字段。如下所示:
我们现在使用Connection对象的query方法结合查询这两张表中的所有数据,查询语句如下:
select * from user inner join user2 where user.age = user2.age;
因此所有的代码如下所示:
const mysql = require('mysql');
/*
createConnection方法创建一个表示与Mysql数据库服务器之间连接的 Connection对象
*/
const connection = mysql.createConnection({
host: 'localhost',
port: 3306,
database: 'my_db',
user: 'root',
password: '123456'
}); /*
connection 对象被创建之后,可以使用该对象的 connect方法建立mysql数据库服务器之间的连接
*/
connection.connect((err) => {
if (err) {
console.log(err);
console.log('数据库连接失败');
} else {
console.log('数据库连接成功');
const sql = 'select * from user inner join user2 where user.age = user2.age';
connection.query(sql, (err, res) => {
if (err) {
console.log('查询数据失败');
} else {
console.log(res);
connection.end();
}
});
}
});
然后我们在命令行中,运行 node app.js 后,可以看到如下所示:
如上图我们可以看到,查询后的数据就是user2表中的数据,user1表的数据被覆盖了,因为user表中的字段和user2表中的字段是一样的,虽然在不同的表中,但是因为字段一样,后面的user2表会把user表中的字段覆盖掉。
解决方法有如下几种:
1. 第一种是给sql语句重复的字段使用别名。这种方法比较繁琐,因为如果表中有多个字段相同的话,要设置多个别名。这种方法不折腾。
2. 第二种方法为在query方法中使用 nestTables属性,并将属性值设置为true。因此会将两个表中的数据以两个对象的形式输出来。如下sql语句改为如下:
{
sql: 'select * from user inner join user2 where user.age = user2.age',
nestTables: true
}
代码如下:
const mysql = require('mysql');
/*
createConnection方法创建一个表示与Mysql数据库服务器之间连接的 Connection对象
*/
const connection = mysql.createConnection({
host: 'localhost',
port: 3306,
database: 'my_db',
user: 'root',
password: '123456'
}); /*
connection 对象被创建之后,可以使用该对象的 connect方法建立mysql数据库服务器之间的连接
*/
connection.connect((err) => {
if (err) {
console.log(err);
console.log('数据库连接失败');
} else {
console.log('数据库连接成功');
const sql = {
sql: 'select * from user inner join user2 where user.age = user2.age',
nestTables: true
};
connection.query(sql, (err, res) => {
if (err) {
console.log('查询数据失败');
} else {
console.log(res);
connection.end();
}
});
}
});
然后我们运行结果如下所示:
如上图可以看到,包含两个对象user和user2,对象里面是各自的数据。
3. 第三种方法是为在query方法中使用nestTables属性并将属性值设定为一个分割字符,这会将被结合的两张表中的数据以一个对象的形式输出。该对象的属性名 为 字段所属表名+分割字符+字段名。
sql语句改为如下:
{
sql: 'select * from user inner join user2 where user.age = user2.age',
nestTables: '_'
}
所有代码如下:
const mysql = require('mysql');
/*
createConnection方法创建一个表示与Mysql数据库服务器之间连接的 Connection对象
*/
const connection = mysql.createConnection({
host: 'localhost',
port: 3306,
database: 'my_db',
user: 'root',
password: '123456'
}); /*
connection 对象被创建之后,可以使用该对象的 connect方法建立mysql数据库服务器之间的连接
*/
connection.connect((err) => {
if (err) {
console.log(err);
console.log('数据库连接失败');
} else {
console.log('数据库连接成功');
const sql = {
sql: 'select * from user inner join user2 where user.age = user2.age',
nestTables: '_'
};
connection.query(sql, (err, res) => {
if (err) {
console.log('查询数据失败');
} else {
console.log(res);
connection.end();
}
});
}
});
然后运行结果如下:
理解mysql执行多表联合查询的更多相关文章
- Node.js的mysql执行多表联合查询
数据库(test)中的表结构(admin.user) //执行多表结合查询 var mysql = require('mysql'); var connection = mysql.createCon ...
- MySQL两个表联合查询并按时间排序
有一张资金记录表,一张金币记录表,想以时间为单位,降序合并排列他们之间的信息,查询SQL如下: select * from (select * from t_money_logs union sele ...
- 你了解MySQL中的多表联合查询吗?
前言: 多表联合查询,其实就是我们MySQL中的join语句,经常会看到有人说join非常影响性能,不建议使用,你知道这是为什么呢?我们究竟可不可以用呢? 测试数据: CREATE TABLE `t2 ...
- mybatis:开发环境搭建--增删改查--多表联合查询(多对一)
什么是mybatisMyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索.MyBatis使用简单的XML或 ...
- yii 多表联合查询的几种方法
yii多表联合查询, 第一种,用command,自己拼接sql语句执行查询 第二种,用AR,model需继承下面的ar,执行queryall或queryrow方法 <?php //applica ...
- MVC5+EF6简单实例---以原有SQLServer数据库两表联合查询为例
有二三年没写代码了,**内的工作就是这样,容易废人!看到园子里这么多大侠朝气蓬勃的,我想也要学点东西并和大家分享,共同进步!快乐每一天,进步每一天!言归正传! 通过最近一段时间对MVC5.EF6的学习 ...
- Dynamic CRM 2013学习笔记(九)CrmFetchKit.js介绍:Fetchxml、多表联合查询, 批量更新
CrmFetchKit.js是一个跨浏览器的一个类库,允许通过JavaScript来执行fetch xml的查询,还可以实现批量更新,分页查询等.目前已支持Chrome 25, Firefox 19 ...
- SharePoint 2013 列表多表联合查询
在SharePoint的企业应用中,遇到复杂的逻辑的时候,我们会需要多表查询:SharePoint和Sql数据表一样,也支持多表联合查询,但是不像Sql语句那样简单,需要使用SPQuery的Joins ...
- hibernate实现多表联合查询
转自:http://blog.sina.com.cn/s/blog_67b9ad8d01010by1.html 以前用sql实现联合查询 是非常简单的事,只需要写sql语句就可以,第一次遇到hiber ...
随机推荐
- 痞子衡嵌入式:一表全搜罗常见低功耗广域物联网协议(NB-IoT/eMTC/LoRa/SigFox...)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是低功耗广域物联网协议. 上一篇痞子衡给大家搜罗了短距离无线通信协议,它是物联网的基础,但它的应用距离比较短,对于长距离的物联网应用鞭长莫 ...
- docker修改国内官方镜像
在正常情况下,docker有一个默认连接的国外官方镜像,在国外的网友访问该官方镜像自然不成问题,但是国内毕竟不是国外,由于国情不同,中国的网络访问国外官方镜像网速一向很慢,而且往往还会遭遇断网的窘境, ...
- 结合JDK源码看设计模式——建造者模式
概念: 将一个复杂对象的构建与它的表示分离.使得同样构建过程可以创建不同表示适用场景: 一个对象有很多属性的情况下 想把复杂的对象创建和使用分离 优点: 封装性好,扩展性好 详解: 工厂模式注重把这个 ...
- Spring Boot 整合 docker
一.什么是docker ? 简介 Docker是一个开源的引擎,可以轻松的为任何应用创建一个轻量级的.可移植的.自给自足的容器.开发者在笔记本上编译测试通过的容器可以批量地在生产环境中部署,包括VMs ...
- 【SpringBoot】拦截器使用@Autowired注入接口为null解决方法
最近使用SpringBoot的自定义拦截器,在拦截器中注入了一个DAO,准备下面作相应操作,拦截器代码: public class TokenInterceptor implements Handle ...
- 视频拉流 Linux安装FFmpeg
1 下载最新源码包并解压 $ wget http://ffmpeg.org/releases/ffmpeg-3.1.3.tar.bz2 $ tar jxvf ffmpeg-.tar.bz2 2安装ya ...
- 一文读懂HTTP/2及HTTP/3特性
摘要: 学习 HTTP/2 与 HTTP/3. 前言 HTTP/2 相比于 HTTP/1,可以说是大幅度提高了网页的性能,只需要升级到该协议就可以减少很多之前需要做的性能优化工作,当然兼容问题以及如何 ...
- 程序员50题(JS版本)(五)
程序21:有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13...求出这个数列的前20项之和. var arr=[]; var count=20; for(var i=0;i<= ...
- finereport报表--动态格间运算 一
一.运算符: ! 绝对值 A2[A2:!1] ; A2 标示从列A纵向第2单元格开始,!1 表示第1个位置的单元格; [A2:!1] 代表索引,表示从A列纵向开始往下,第1个单元格的位置的索引 ...
- js中的new()到底做了些什么??
要创建 Person 的新实例,必须使用 new 操作符.以这种方式调用构造函数实际上会经历以下 4个步骤:(1) 创建一个新对象:(2) 将构造函数的作用域赋给新对象(因此 this 就指向了这个新 ...