Python-数据库连表查询、子查询
连表查询
【实例】通过例子来熟悉连表查询的概念
# 第一步:建表
# 建立英雄职业分类表格
create table classification(
id int,
name varchar(20)
);
# 英雄属性表格
create table hero(
id int primary key auto_increment,
name varchar(20),
sex enum('male','female') not null default 'male',
cd int, # 技能时间
cha_id int # 英雄职业
);
# 插入数据
insert into classification values
(200,'法师'),
(201,'战士'),
(202,'射手'),
(203,'辅助');
insert into hero(name,sex,cd,cha_id) values
('莫甘娜','female',40,200),
('盖伦','male',50,201),
('赵信','male',48,201),
('女警','female',35,202),
('梦魇','male',30,200),
('阿卡丽','female',28,204)
;
笛卡尔积
交叉连接实例:在没有任何条件连接的情况下联合两张表进行查询,结果会以笛卡尔积的形式显示
mysql> select * from hero,classification;
+----+-----------+--------+------+--------+------+--------+
| id | name | sex | cd | cha_id | id | name |
+----+-----------+--------+------+--------+------+--------+
| 1 | 莫甘娜 | female | 40 | 200 | 200 | 法师 |
| 1 | 莫甘娜 | female | 40 | 200 | 201 | 战士 |
| 1 | 莫甘娜 | female | 40 | 200 | 202 | 射手 |
| 1 | 莫甘娜 | female | 40 | 200 | 203 | 辅助 |
| 2 | 盖伦 | male | 50 | 201 | 200 | 法师 |
| 2 | 盖伦 | male | 50 | 201 | 201 | 战士 |
| 2 | 盖伦 | male | 50 | 201 | 202 | 射手 |
| 2 | 盖伦 | male | 50 | 201 | 203 | 辅助 |
| 3 | 赵信 | male | 48 | 201 | 200 | 法师 |
| 3 | 赵信 | male | 48 | 201 | 201 | 战士 |
| 3 | 赵信 | male | 48 | 201 | 202 | 射手 |
| 3 | 赵信 | male | 48 | 201 | 203 | 辅助 |
| 4 | 女警 | female | 35 | 202 | 200 | 法师 |
| 4 | 女警 | female | 35 | 202 | 201 | 战士 |
| 4 | 女警 | female | 35 | 202 | 202 | 射手 |
| 4 | 女警 | female | 35 | 202 | 203 | 辅助 |
| 5 | 梦魇 | male | 30 | 200 | 200 | 法师 |
| 5 | 梦魇 | male | 30 | 200 | 201 | 战士 |
| 5 | 梦魇 | male | 30 | 200 | 202 | 射手 |
| 5 | 梦魇 | male | 30 | 200 | 203 | 辅助 |
| 6 | 阿卡丽 | female | 28 | 204 | 200 | 法师 |
| 6 | 阿卡丽 | female | 28 | 204 | 201 | 战士 |
| 6 | 阿卡丽 | female | 28 | 204 | 202 | 射手 |
| 6 | 阿卡丽 | female | 28 | 204 | 203 | 辅助 |
+----+-----------+--------+------+--------+------+--------+
24 rows in set (0.00 sec)
【结论】实际使用时应该是不会希望在笛卡尔积表中查找信息,毕竟有大量的信息冗余。我们希望的是能够通过一种连接关系,将两张有关系的表组合成一张表。
内连接
内连接,实现两张表中相互匹配的行进行连接,就像hero表中的cha_id与classification里的id是相匹配,匹配格式如下:
select * from 表1 inner join 表2 on 条件
select * from 表1,表2,表3 where 表1.字段1=表2.字段1 and 表2.字段2 = 表3.字段1
mysql> select * from hero inner join classification on hero.cha_id = classification.id;
# 如果表格的长度比较长不方便操作的话,给他重命名以下
mysql> select * from hero inner join classification as cla on hero.cha_id = cla.id;
+----+-----------+--------+------+--------+------+--------+
| id | name | sex | cd | cha_id | id | name |
+----+-----------+--------+------+--------+------+--------+
| 1 | 莫甘娜 | female | 40 | 200 | 200 | 法师 |
| 2 | 盖伦 | male | 50 | 201 | 201 | 战士 |
| 3 | 赵信 | male | 48 | 201 | 201 | 战士 |
| 4 | 女警 | female | 35 | 202 | 202 | 射手 |
| 5 | 梦魇 | male | 30 | 200 | 200 | 法师 |
+----+-----------+--------+------+--------+------+--------+
左外连接
连接的两张表中以左侧的表为准,右侧的表匹配左侧的表,优先显示左表全部记录,显示顺序以左侧为主
用法
select * from 表1 left join 表2 on 条件
mysql> select * from hero left join classification as cla on hero.cha_id = cla.id;
+----+-----------+--------+------+--------+------+--------+
| id | name | sex | cd | cha_id | id | name |
+----+-----------+--------+------+--------+------+--------+
| 1 | 莫甘娜 | female | 40 | 200 | 200 | 法师 |
| 5 | 梦魇 | male | 30 | 200 | 200 | 法师 |
| 2 | 盖伦 | male | 50 | 201 | 201 | 战士 |
| 3 | 赵信 | male | 48 | 201 | 201 | 战士 |
| 4 | 女警 | female | 35 | 202 | 202 | 射手 |
| 6 | 阿卡丽 | female | 28 | 204 | NULL | NULL |
+----+-----------+--------+------+--------+------+--------+
【结论】左侧的表全部显示,右侧匹配左侧,缺失项为NULL
右外连接
连接的两张表中以右侧的表为准,左侧的表匹配右侧的表,优先显示左表全部记录,显示顺序以左侧为主
select * from 表1 right join 表2 on 条件
mysql> select * from hero right join classification as cla on hero.cha_id = cla.id;
+------+-----------+--------+------+--------+------+--------+
| id | name | sex | cd | cha_id | id | name |
+------+-----------+--------+------+--------+------+--------+
| 1 | 莫甘娜 | female | 40 | 200 | 200 | 法师 |
| 2 | 盖伦 | male | 50 | 201 | 201 | 战士 |
| 3 | 赵信 | male | 48 | 201 | 201 | 战士 |
| 4 | 女警 | female | 35 | 202 | 202 | 射手 |
| 5 | 梦魇 | male | 30 | 200 | 200 | 法师 |
| NULL | NULL | NULL | NULL | NULL | 203 | 辅助 |
+------+-----------+--------+------+--------+------+--------+
全外连接
根据匹配项连接两张表,显示所有内容,缺失项以NULL填充
select * from 表1 full join 表2 on 条件
【注意】目前各个DBMS对外连接的支持星泪不尽相同,MySQL仅仅支持左右两个外连接,并不支持全外连接
在MySQL中实现全外连接
select * from 表1 right join 表2 on 条件
union
select * from 表1 left join 表2 on 条件
+------+-----------+--------+------+--------+------+--------+
| id | name | sex | cd | cha_id | id | name |
+------+-----------+--------+------+--------+------+--------+
| 1 | 莫甘娜 | female | 40 | 200 | 200 | 法师 |
| 5 | 梦魇 | male | 30 | 200 | 200 | 法师 |
| 2 | 盖伦 | male | 50 | 201 | 201 | 战士 |
| 3 | 赵信 | male | 48 | 201 | 201 | 战士 |
| 4 | 女警 | female | 35 | 202 | 202 | 射手 |
| 6 | 阿卡丽 | female | 28 | 204 | NULL | NULL |
| NULL | NULL | NULL | NULL | NULL | 203 | 辅助 |
+------+-----------+--------+------+--------+------+--------+
符合条件的连接查询
# 找出cd时间大于40的英雄名称以及该英雄的职业属性
mysql> select hero.name,cla.name,hero.cd from hero inner join classification as cla on hero.cha_id = cla.id where cd> 40;
+--------+--------+------+
| name | name | cd |
+--------+--------+------+
| 盖伦 | 战士 | 50 |
| 赵信 | 战士 | 48 |
+--------+--------+------+
# 以内连接的方式查询hero和classification表,并且以age字段的升序方式显示
mysql> select * from hero inner join classification as cla on hero.cha_id = cla.id order by cd asc;
+----+-----------+--------+------+--------+------+--------+
| id | name | sex | cd | cha_id | id | name |
+----+-----------+--------+------+--------+------+--------+
| 5 | 梦魇 | male | 30 | 200 | 200 | 法师 |
| 4 | 女警 | female | 35 | 202 | 202 | 射手 |
| 1 | 莫甘娜 | female | 40 | 200 | 200 | 法师 |
| 3 | 赵信 | male | 48 | 201 | 201 | 战士 |
| 2 | 盖伦 | male | 50 | 201 | 201 | 战士 |
+----+-----------+--------+------+--------+------+--------+
9.10 子查询
- 将一个查询语句前台到另一个查询语句中;
- 内层查询语句的结果可以作为外层查询语句的条件;
- 子查询中可以包含IN,NOT IN,ANY,ALL,EXISTS和 NOT EXISTS等关键字;EXISTS关字键字表示存在。在使用EXISTS关键字时,内层查询语句不返回查询的记录。而是返回一个真假值。True或False,当返回True时,外层查询语句将进行查询;当返回值为False时,外层查询语句不进行查询
- 还可以包含比较运算符 = != > <
【举例1】
# 带in关键字的子查询
# 查询cd时间在40秒以上的英雄职业有哪些
第一步:通过hero查询cd时间在40秒的职业id
mysql> select cha_id from hero where cd>40;
+--------+
| cha_id |
+--------+
| 201 |
| 201 |
+--------+
第二步:从第一步的查询到的id在classification里找到对应的name
mysql> select name from classification where id in (201);
+--------+
| name |
+--------+
| 战士 |
+--------+
# 将两部结合在一起
mysql> select name from classification where id in (select cha_id from hero where cd>40);
+--------+
| name |
+--------+
| 战士 |
+--------+
【举例2】
# 查询平均cd在30以上的英雄职业,平均cd
【方法一】先查平均cd>30的职业id,平均cd,查出结果在之后再连表
mysql> select c.name,avg_cd from classification as c inner join (select avg(cd) as avg_cd ,cha_id from hero group by cha_id having avg(cd) > 30 )as tem on tem.cha_id = c.id;
+--------+---------+
| name | avg_cd |
+--------+---------+
| 法师 | 35.0000 |
| 战士 | 49.0000 |
| 射手 | 35.0000 |
+--------+---------+
3 rows in set (0.00 sec)
【方法二】先查各职业的平均cd,查出结果在之后再连表筛选
mysql> select c.name,avg_cd from classification as c inner join (select avg(cd) as avg_cd,cha_id from hero group by cha_id) as tem on tem.cha_id = c.id where avg_cd > 30;
+--------+---------+
| name | avg_cd |
+--------+---------+
| 法师 | 35.0000 |
| 战士 | 49.0000 |
| 射手 | 35.0000 |
+--------+---------+
【注意】
如果最终需要的结果只出现在一张表中,可以用子查询解决问题
如果最终需要的结果出现在两张表中,那么最后用的一定是连表查询
能用连表的时候就用连表,效率比子查询快
【举例三】
# 运算符的使用
# 查看法师职业有谁
mysql> select name from hero where cha_id = (select id from classification where name = '法师');
+-----------+
| name |
+-----------+
| 莫甘娜 |
| 梦魇 |
+-----------+
# 查询大于所有人平均cd的英雄名与cd
mysql> select name,cd from hero where cd > (select avg(cd) from hero);
+-----------+------+
| name | cd |
+-----------+------+
| 莫甘娜 | 40 |
| 盖伦 | 50 |
| 赵信 | 48 |
+-----------+------+
# 扩展练习:查询大于职业平均cd的英雄名、cd
mysql> select hero.name,hero.cd from hero inner join (select cha_id,avg(cd) as avg_cd from hero group by cha_id) as tem on tem.cha_id = hero.cha_id where tem.avg_cd <hero.cd;
+-----------+------+
| name | cd |
+-----------+------+
| 莫甘娜 | 40 |
| 盖伦 | 50 |
+-----------+------+
【举例四】
# 带EXISTS关键字的子查询
# EXISTS关字键字表示存在。在使用EXISTS关键字时,内层查询语句不返回查询的记# 录。而是返回一个真假值。True或False当返回True时,外层查询语句将进行查询 # 当返回值为False时,外层查询语句不进行查询
# classification表中存在203,True
mysql> select * from hero where exists (select id from classification where id = 203);
+----+-----------+--------+------+--------+
| id | name | sex | cd | cha_id |
+----+-----------+--------+------+--------+
| 1 | 莫甘娜 | female | 40 | 200 |
| 2 | 盖伦 | male | 50 | 201 |
| 3 | 赵信 | male | 48 | 201 |
| 4 | 女警 | female | 35 | 202 |
| 5 | 梦魇 | male | 30 | 200 |
| 6 | 阿卡丽 | female | 28 | 204 |
+----+-----------+--------+------+--------+
# classification表中存在205,False
mysql> select * from hero where exists (select id from classification where id = 205);
Empty set (0.00 sec)
总结
select干了什么:首先是根据条件对每行记录进行检索,再根据其他条件进行字段筛选
数据库数据导入
# 准备表、记录
mysql> create database 数据库名;
mysql> use 数据库名;
mysql> source init.sql路径;
Python-数据库连表查询、子查询的更多相关文章
- Database学习 - mysql 数据库 多表/复合/子 查询
多表查询 多表查询,基本规则,通过两表有关联字段的进行条件匹配查询 内连接查询 方式一: SELECT 查看字段名[,查看字段名] FROM 一表名,二表名 WHERE 一/二表.字段 = 一/二表. ...
- oracle 基础SQL语句 多表查询 子查询 分页查询 合并查询 分组查询 group by having order by
select语句学习 . 创建表 create table user(user varchar2(20), id int); . 查看执行某条命令花费的时间 set timing on: . 查看表的 ...
- Python-select 关键字 多表查询 子查询
sql 最核心的查询语句!!!! 增删改 单表查询 select语句的完整写法 关键字的书写顺序 执行顺序 多表查询 笛卡尔积 内连接 左外连接 右外连接 全外连接 通过合并左外连接和右外连接 子查询 ...
- Oracle(2)之多表查询&子查询&集合运算
多表查询 笛卡尔积 同时查询多张表时,每张表的每条数据都要和其它表的每条数据做组合.如下栗子,我们发现产生的总记录数是 56 条,还发现 emp 表是 14 条,dept 表是 4 条,56 条正是 ...
- [sql Server]除非另外还指定了TOP 或 FOR XML,否则,ORDER BY 子句在视图、内联函数、派生表、子查询和公用表表达式中无效
今天遇到一个奇怪的问题,项目突然要从mysql切换到sql server数据库,包含order by 子句的嵌套子查询报错. 示例:select top 10 name,age,sex from ( ...
- 【知识库】-数据库_MySQL之基本数据查询:子查询、分组查询、模糊查询
简书作者:seay 文章出处: 关系数据库SQL之基本数据查询:子查询.分组查询.模糊查询 回顾:[知识库]-数据库_MySQL常用SQL语句语法大全示例 Learn [已经过测试校验] 一.简单查询 ...
- sql:除非另外还指定了 TOP 或 FOR XML,否则,ORDER BY 子句在视图、内联函数、派生表、子查询
执行sql语句: select * from ( select * from tab where ID>20 order by userID desc ) as a order by date ...
- java数据库编程之嵌套子查询及exists的使用
第四章:高级查询(二) 4.1:exists和not exists子查询 4.1.1:exists子查询 用exists作为子查询的where条件 语法:select,,,,,,from 表名 w ...
- ORDER BY 子句在视 图、内联函数、派生表、子查询和公用表表达式中无效
SQL语句: select * from (select distinct t2.issue,cashmoney from (select distinct issue from lot_gamepa ...
- 【数据库】SQL经典面试题 - 数据库查询 - 子查询应用二
上节课我们通过子查询,完成了查询的最高分学生的需求,今天我们来学习子查询的分类,以及通过子查询来完成工作中经常遇到一些个性化需求. 子查询概念: 一个SELECT语句嵌套在另一个SELECT语句中,子 ...
随机推荐
- Java-JsonUtil工具类
import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; i ...
- [学习笔记] 可持久化线段树&主席树
众所周知,线段树是一个非常好用也好写的数据结构, 因此,我们今天的前置技能:线段树. 然而,可持久化到底是什么东西? 别急,我们一步一步来... step 1 首先,一道简化的模型: 给定一个长度为\ ...
- Jmeter接口测试之用例数据分离
之前我们的用例数据都是配置在 Jmeter Http 请求中,每次需要增加,修改用例都需要打开 jmeter 重新编辑,当用例越来越多的时候,用例维护起来就越来越麻烦,有没有好的方法来解决这种情况呢? ...
- wind本地MySQL数据到hive的指定路径,Could not create file
一:使用:kettle:wind本地MySQL数据到hive的指定路径二:问题:没有root写权限网上说的什么少jar包,我这里不存在这种情况,因为我自己是导入jar包的:mysql-connecto ...
- MVN 报错1
找不到mapper映射文件 只打包了下面这些 所以pom.xml文件中添加 <!-- 如果不添加此节点mybatis的mapper.xml文件都会被漏掉. --> <build> ...
- XML -- XML基础知识
1.XML的结构 XML的结构采用的是树结构,树结构就是一种一对多的关系结构. XML必定有一个根节点.因为,在解析这个XML时,需要有个起始位置进行遍历解析,这个跟节点就是起始位置. 2.XML的元 ...
- 51 Nod 1272 简单思维题
1272 最大距离 题目来源: Codility 基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题 收藏 关注 给出一个长度为N的整数数组A,对于每一个数组元素 ...
- TTTTTTTTTTTTT CF#365 div2 B 统计点
B. Mishka and trip time limit per test 1 second memory limit per test 256 megabytes input standard i ...
- 【CUDA 基础】4.2 内存管理
title: [CUDA 基础]4.2 内存管理 categories: - CUDA - Freshman tags: - CUDA内存管理 - CUDA内存分配和释放 - CUDA内存传输 - 固 ...
- carographer流程
node_main.cc 93 Run启动 58 Node初始化 64 node.StartTrajectoryWithDefault ...