目录

基本查询语句及方法

测试数据创建

如果在windows系统中,插入中文字符,select的结果为空白,可以将所有字符编码统一设置成gbk(或者参照我安装配置MySQL的博客,将所有字符编码设置为 utf8)

创建数据库与表

create database db1;
use db1; create table emp(
id int not null unique auto_increment,
# 表内没有字段是primary key,innodb的机制,一个表没有primaryk key时会自动将 not null + unique的键自动升级为 primary key 主键
name varchar(20) not null,
sex enum('male','female') not null default 'male', # 大部分是男的
age int(3) unsigned not null default 28, # 这个3 只限制了显示宽度,并不影响存储
hire_date date not null,
post varchar(50),
post_comment varchar(100),
salary double(15,2),
office int, # 一个部门一间办公室,一个门牌号
depart_id int # 暂不建立外键关系
);

插入表记录数据

# 三个部门:教学,销售,运营
# 以下是教学部
insert into emp(name,sex,age,hire_date,post,salary,office,depart_id) values
('jason','male',18,'20170301','张江第一帅形象代言',7300.33,401,1),
('egon','male',78,'20150302','teacher',1000000.31,401,1),
('kevin','male',81,'20130305','teacher',8300,401,1),
('tank','male',73,'20140701','teacher',3500,401,1),
('owen','male',28,'20121101','teacher',2100,401,1),
('jerry','female',18,'20110211','teacher',9000,401,1),
('nick','male',18,'19000301','teacher',30000,401,1),
('sean','male',48,'20101111','teacher',10000,401,1), # 以下是销售部门
('歪歪','female',48,'20150311','sale',3000.13,402,2),
('丫丫','female',38,'20101101','sale',2000.35,402,2),
('丁丁','female',18,'20110312','sale',1000.37,402,2),
('星星','female',18,'20160513','sale',3000.29,402,2),
('格格','female',28,'20170127','sale',4000.33,402,2), # 以下是运营部门
('张野','male',28,'20160311','operation',10000.13,403,3),
('程咬金','male',18,'19970312','operation',20000,403,3),
('程咬银','female',18,'20130311','operation',19000,403,3),
('程咬铜','male',18,'20150411','operation',18000,403,3),
('程咬铁','female',18,'20140512','operation',17000,403,3);

数据展示

常见结果排版

select * from emp;

另一种结果排版 \G

当表字段特别多的时候,结果的排版可能会出现混乱的现象,你可以在语句最后加 \G 来改变排版,方便查看

比较差的展示结果,这种情况就非常适合用 \G 来看数据

简单查询语句的书写与执行顺序

查询语句书写

查询出 emp 表中id 在 3~6 的员工详细信息

思路:从emp 表中,查 id 大于3 且 小于 6 的数据

语句

select * from emp where id > 3 and id < 6;

这里仅为了演示书写顺序,不考虑其他写法

执行顺序

最先执行的是 from,来确定到底是哪张表

然后执行 where,根据条件筛选数据

最后执行 select,来拿筛选出来的数据中的(某些,select 后面跟的字段名)字段

科普-- 起别名

关键字 as

  • 可以给表起别名
  • 可以给查询出来的虚拟表(查询结果)起别名
  • 可以给字段起别名
  • 可以给函数的结果取别名(max、min 等)

写法

要起别名的对象 as 别名 或者 直接 要起别名的对象 别名

不过尽量还是用as ,不用as 可能语义不明确

给函数结果起别名

... max(hire_date) as max_date ...

给表起别名

select ... from emp as t1 ....

给查询出来的虚拟表取别名

... (select * from emp) as t2 ...

给字段起别名

select name as '姓名', post '部门' from emp;

可以对字段做四则运算(加减乘数)

查一下 jason 的年薪

select name as '姓名', salary * 12 as '年薪' from emp where name = 'jason';

concat 格式化拼接字段

可以按指定格式拼接字段

select concat('oldboy_', name, '_', id), sex, post, salary from emp;

concat_ws 用指定字符拼接字段

select concat_ws(':', name, sex, age) from emp;

定制化查询结果

复杂查询实现小窍门:

写sql语句的时候,千万不要急着一口气写完(切忌心浮气躁)

前期按照歩鄹一步步写将前一步操作产生的结果当成是一张新的表,然后基于该表再进行其他操作,写一步查询看一下结果然后基于当前结果再往后写

我们查询数据一般都需要做一些过滤,单纯靠 select * from 表名; 就无法达到要求,此时我们可以通过

常见的数据定制化关键字(非多表查询)

  • where 条件过滤数据

    一般配合一堆聚合函数使用

  • group by 对数据进行分组

    • having 对分组的结果再进行条件过滤(必须跟在 group by 语句后面)

  • distinct 对查询结果去重

  • order by 对查询结果排序

  • limit 限制显示数据条数

where 结合过滤条件过滤结果

> < = != <= >= <> 比较运算符

# 查询出 emp 表中, id 大于3 的员工信息
select * from emp where id > 3;

and or not 与或非连接多个条件

一般用来连接多个条件

and 并且

or 或

not 非

is

针对 null 判断的时候只能用 is 不能用 =

案例

# and
# 1.查询id大于等于3小于等于6的数据
select id,name from emp where id >= 3 and id <= 6; # or
# 2.查询薪资是20000或者18000或者17000的数据
select * from emp where salary = 20000 or salary = 18000 or salary = 17000; # not
# 5.查询id小于3或者大于6的数据
select * from emp where id not between 3 and 6; # is
# 7.查询岗位描述为空的员工名与岗位名 针对null不能用等号,只能用is
select name,post from emp where post_comment = NULL; # 查询为空,不能用 = 判断空!
select name,post from emp where post_comment is NULL;
select name,post from emp where post_comment is not NULL;

范围

between ... and ... 表示范围(整型字段可用)

in

and or not 结果其他关键字组合

案例

# between ... and ...
# 1.查询id大于等于3小于等于6的数据
select * from emp where id between 3 and 6; # in
# 2.查询薪资是20000或者18000或者17000的数据
select * from emp where salary in (20000,18000,17000); # and or not
# 在上一模块中有案例

exists 是否存在

# EXISTS 关键字表示存在
# 返回值是 True 或者 False
select * from emp where exists (select id from dep where id > 203); # 用到了下面的子查询(知识点)

like 模糊匹配

一般包含有 ... 之类的查询都会用 like 关键字,模糊匹配

小技巧

是否含有用 % 包围起来

固定长度用 来占位,一个 _ 表示一个字符

案例

# 3.查询员工姓名中包含o字母的员工姓名和薪资
select name,salary from emp where name like '%o%'; # 4.查询员工姓名是由四个字符组成的员工姓名与其薪资
# 方案一:用四个 _ 代替四个字符
select name,salary from emp where name like '____';
# 方案二:利用 char_length(字段名) 来获取字段长度
select name,salary from emp where char_length(name) = 4; # 注意 sql_mode 里 PAD_CHAR_TO_FULL_LENGTH 这么个约束,否则 char类型定长可能会受影响

regexp 正则

可用正则规则匹配字符串作为查询条件

select * from emp where name regexp '^j.*(n|y)$';

group by 分组

分组之后应该做到最小单位是组,而不应该再展示组内的单个信息

MySQL 中分组之后,只能拿到分组的字段信息无法直接获取其他字段信息

但是你可以通过其他方法(如:聚合函数)间接地获取

分组相当于打包,聚合函数可以对包里每一个元素进行处理,最终拿出想要的

刚开始查询表,一定要按照最基本的步骤,先确定是哪张表,再确定查这张表也没有限制条件,再确定是否需要分类,最后再确定需要什么字段对应的信息

应用场景

每个部门的平均薪资,男女比例等

分组严格模式(推荐开启)

select * from emp group by post; 如果你的MySQL不报错,说明分组的严格模式没有设置

--> only_full_group_by 限制分组

非分组严格模式下

设置分组严格模式(其他的严格模式别忘写了)

set global sql_mode='strict_trans_tables,pad_char_to_full_length,only_full_group_by';

pad_char_to_full_length 验证 char varchar占用空间用,会影响 char_length() 获取的长度

strict_trans_tables 限制 sql 不能不合规则的直接报错

分组严格模式下执行,直接报错(day37.emp.id --> 数据库day37.表emp.字段id),字段不在分组里

having 分组条件

havingwhere 是一模一样的,也是用来筛选数据的,但是 having 必须在 group by 后面使用

where是对整体数据做一个初步的筛选,而having是对分组之后的数据再进行一次针对性的筛选

select post, avg(salary) from emp where age > 30 group by post having avg(salary) > 10000;

统计各部门年龄在30岁以上的员工平均工资,并且保留平均工资大于10000的部门

分组结合聚合函数

只能在分组之后使用(如果没有写group by ,默认所有数据就是一组

也可以说是 where 不能用聚合函数(执行顺序过了 where之后就可也以算分组之后了--> 执行顺序)

max min avg sum count

能够获取到分组之后除了分组依据以外的字段,将该字段作为函数的条件

# 强调:只要分组了,就不能够再“直接”查找到单个数据信息了,只能获取到组名
# 2.获取每个部门的最高工资
# 以组为单位统计组内数据>>>聚合查询(聚集到一起合成为一个结果)
# 每个部门的最高工资
select post,max(salary) from emp group by post;
# 每个部门的最低工资
select post,min(salary) from emp group by post;
# 每个部门的平均工资
select post,avg(salary) from emp group by post;
# 每个部门的工资总和
select post,sum(salary) from emp group by post; # 每个部门的人数
# 在统计分组内个数的时候,填写任意非空字段都可以完成计数(推荐使用能够标识数据的字段,比如id字段)
select post,count(id) from emp group by post;

group_concat 分组拼接记录字段

能够获取到分组之后除了分组依据以外的字段,还能做拼接操作

# 3.查询分组之后的部门名称和每个部门下所有的学生姓名
# group_concat(分组之后用)不仅可以用来显示除分组外字段还有拼接字符串的作用
select post,group_concat(name) from emp group by post; select post,group_concat(name,"_SB") from emp group by post; select post,group_concat(name,": ",salary) from emp group by post; select post,group_concat(salary) from emp group by post; # 4.补充concat(不分组时用)拼接字符串达到更好的显示效果 as语法使用(前面有讲到)
select name as 姓名,salary as 薪资 from emp;
select concat("NAME: ",name) as 姓名,concat("SAL: ",salary) as 薪资 from emp; /*
concat 在不分组情况下使用
group_concat 用在分组之后
*/

distinct 去重

对整个查询(查询出的虚拟表)结果中重复的数据去重,重复必须数据是一模一样的才能去重,只要有一个(字段)不一样都不能算是重复的数据

如果你查询出来的数据中包含主键(非空且唯一),那么不可能去重成功

个人推荐理解成作用于上一步查询结果的(不要以为像order by一样修饰某个字段)

select distinct age, id from emp;

查询结果有重复的情况下,会自动去除重复

select distinct sex, age, id from emp order by sex, age asc;

记录没有重复,distinct 无效

order by 排序

order by 有升序(ASC)、降序(DESC)两种排序规则,默认升序

多个排序字段时,放前面的作为优先排序条件,相同再按照后面的字段排序

select post, avg(salary) from emp where age>10 group by post having avg(salary) > 1000 order by avg(salary);

单个字段排序

select * from emp order by sex, age asc;

多字段排序

limit 限制展示数据的条数

select * from emp limit 3;

当limit 只有一个参数的时候,表示的是从第一条开始只展示几条

select * from emp limit 5,5;

当limit 有两个参数的时候,第一个参数表的起始位置,第二个参数表示从起始位置开始往后展示的条数

练习

查询工资最高的人的详细信息

select * from emp order by salary desc limit 1;

应用场景

分页数据展示,每页只展示多少条,每页展示的内容,是第几条到第几条

究极版执行顺序书写顺序

书写顺序(除了 select ... from ... 其他是可选的)

select distinct 字段1,字段2(有分组时只能写分组字段或聚合函数) from 表名
where 条件(不能用聚合函数)
group by (单个)字段
having 条件
order by 字段1,字段2 排序规则
limit 起始位置,条数;

执行顺序

from
where
group by
having # 必须跟在 group by 后面
# 后4个顺序不太重要,也不一定对
order by
limit
distinct
select

多表查询

前言

在昨天的知识点中,员工信息全存为一张表不太合理,我们选择了拆表,分析了表关系,最终拆分成了员工表与部门表两张表,表示拆分好了,但怎么去查询数据呢?

实现多表查询,有下面两种方式

  • 联表查询
  • 子查询

每一次的查询结果都是一张虚拟表,我们可以用 as 关键字给虚拟表取别名,然后将其当做普通表作为查询条件使用

测试数据创建

创建数据库与表

create database db2;
use db2; create table dep(
id int,
name varchar(20)
); create table emp(
id int primary key auto_increment,
name varchar(20),
sex enum('male','female') not null default 'male',
age int,
dep_id int
);

插入表记录数据

insert into dep values
(200,'技术'),
(201,'人力资源'),
(202,'销售'),
(203,'运营'); insert into emp(name,sex,age,dep_id) values
('jason','male',18,200),
('egon','female',48,201),
('kevin','male',38,201),
('nick','female',28,202),
('owen','male',18,200),
('jerry','female',18,204); # 当初为什么我们要分表,就是为了方便管理,在硬盘上确实是多张表,但是到了内存中我们应该把他们再拼成一张表进行查询才合理

笛卡尔集/积 -- 科普

笛卡尔集的列数为每个表的列数之和,笛卡尔集的行数为每个表的行数相乘

我们经常做的多表查询就是在笛卡尔集中通过筛选条件得出的数据,所以笛卡尔集是多表查询的基础

select * from emp, dep; 结果是一个笛卡尔集/积

select * from emp;

select * from dep;

后面跟条件也可以达到多表查询

select * from emp, dep where emp.dep_id = dep.id

联表查询

通过下面四种连接语句来实现多表查询

inner/left/right join ...左右是表 on ... 后面可以跟条件

内连接 inner join ... on

仅保留两张表有对应关系的记录

select * from emp inner join dep on emp.dep_id=dep.id;

左连接 left join ... on

在内连接的基础上保留左表没有对应关系的记录

select * from emp left join dep on emp.dep_id = dep.id;

右连接 right join ... on

在内连接的基础上保留右表没有对应关系的记录

select * from emp right join dep on emp.dep_id = dep.id;

全连接 union ... on

不常用

在内连接的基础上保留左、右面表没有对应关系的的记录

写法:只需要在左连接和右连接的sql 语句中间加个union就变成了全连接

select * from emp left join dep on emp.dep_id = dep.id  # 左连接 sql,后面不要加分号
union
select * from emp right join dep on emp.dep_id = dep.id; # 右连接 sql

子查询

将一个查询语句用括号括起来,将查询结果(虚拟表)作为另外一个 sql 语句的查询条件

ps:表的查询结果可以作为其他表的查询条件,也可以通过起别名的方式把它作为一张虚拟表跟其他表做关联查询

# 1.查询部门是技术或者人力资源的员工信息

# 思路
# 先获取技术部和人力资源部的id号,再去员工表里面根据前面的id筛选出符合要求的员工信息
select * from emp where dep_id in (select id from dep where name = "技术" or name = "人力资源");

select * from emp;

select id from dep where name = "技术" or name = "人力资源";

# 2.每个部门最新入职的员工

# 思路
# 先查每个部门最新入职的员工,再按部门对应上联表查询 select t1.id, t1.name, t1.hire_date, t1.post from emp as t1
inner join
# 根据分组求出最新入职员工
(select post,max(hire_date) as max_date from emp group by post) as t2
on t1.post = t2.post
where t1.hire_date = t2.max_date;

完整表信息

练习小案例

# 平均年龄在25岁以上的部门名

# 联表
select dep.name from dep inner join emp on emp.dep_id = dep.id group by dep.name having avg(age) > 25; # 子查询
select name from dep where dep.id in (select dep_id from emp group by dep_id having avg(age) > 25);

联表查询思路

1.先把两张表连起来,把结果查出来看看,再接着往下写

select * from dep inner join emp on emp.dep_id = dep.id;

2.再根据部门分组,筛选出平均年龄大于25的部门名

group by dep.name having avg(age) > 25

合并上一步的语句(* --> dep.name)

select dep.name from dep inner join emp on emp.dep_id = dep.id group by dep.name having avg(age) > 25;

子查询思路

1.先根据 部门id 分组,查出平均年龄大于 25多的部门id

select dep_id from emp group by dep_id having avg(age) > 25;

2.将上一步的 部门id 作为筛选条件 联合上部门表查出来

select name from dep where dep.id in (select dep_id from emp group by dep_id having avg(age) > 25);

MySQL-复杂查询及条件-起别名-多表查询-04的更多相关文章

  1. mysql数据库补充知识2 查询数据库记录信息之单表查询

    一 单表查询的语法 SELECT 字段1,字段2... FROM 表名 WHERE 条件 GROUP BY field HAVING 筛选 ORDER BY field LIMIT 限制条数 二 关键 ...

  2. mysql基础教程(二)-----分组函数、多表查询、常见函数

    分组函数 什么是分组函数 分组函数作用于一组数据,并对一组数据返回一个值. 组函数类型 • AVG() • COUNT() • MAX() • MIN() • SUM() 组函数语法 AVG(平均值) ...

  3. 【MySQL】MySQL进阶(外键约束、多表查询、视图、备份与恢复)

    约束 外键约束 外键约束概念 让表和表之间产生关系,从而保证数据的准确性! 建表时添加外键约束 为什么要有外键约束 -- 创建db2数据库 CREATE DATABASE db2; -- 使用db2数 ...

  4. mysql数据库补充知识3 查询数据库记录信息之多表查询

    一 介绍 准备表 company.employeecompany.department 复制代码 #建表 create table department( id int, name varchar(2 ...

  5. MySQL入门,第八部分,多表查询(一)

    一.数据库脚本 #-------------------------------------------------------------------------------- #--------- ...

  6. MySQL数据库的创建和操作以及多表查询

    创建数据库: CREATE DATABASE 数据库名称; 查看所有的数据库: SHOW DATABASES; 操作指定数据库: USE 数据库名称; 查看当前所操作的数据库: SELECT DATA ...

  7. MySQL入门,第八部分,多表查询(二)

    嵌套查询 嵌套查询是指一个SELECT-FROM-WHERE查询块嵌入在另一个SELECT-FROM-WHERE查询块的WHERE子句中的查询 注意: 只有当连接查询投影列的属性来自于一个关系表时才能 ...

  8. Mysql常用sql语句(14)- 多表查询

    测试必备的Mysql常用sql语句,每天敲一篇,每次敲三遍,每月一循环,全都可记住!! https://www.cnblogs.com/poloyy/category/1683347.html 前言 ...

  9. Django Mysql数据库-基于双下划线的跨表查询

    一.基于双下划线的跨表查询 Django 还提供了一种直观而高效的方式在查询(lookups)中表示关联关系,它能自动确认 SQL JOIN 联系.要做跨关系查询,就使用两个下划线来链接模型(mode ...

随机推荐

  1. ORACLE表名与列名小写转成大写

    批量将表名变为大写 begin for c in (select table_name tn from user_tables where table_name <> upper(tabl ...

  2. ANDROID_ID

    在设备首次启动时,系统会随机生成一个64位的数字,并把这个数字以16进制字符串的形式保存下来,这个16进制的字符串就是ANDROID_ID,当设备被wipe后该值会被重置.可以通过下面的方法获取: i ...

  3. js类型判断:typeof与instanceof

    typeof用以获取一个变量或者表达式的类型,typeof一般只能返回如下几个结果: number,boolean,string,function(函数),object(NULL,数组,对象),und ...

  4. 摘抄java基础

    1.Java中Static的相关用法总结?(静态方法:静态变量:静态代码块) public static void main(String args[])执行的关键,在于有static.有了stati ...

  5. linux下的开源NFC协议栈

    1. 协议栈名称 neardal 2. 源码 https://github.com/connectivity/neardal.git 3. 由谁维护? intel 4. 基于neardal的nfc协议 ...

  6. Oracle登录认证

    oracle 登录认证 Table of Contents 1. 简介 2. authentication_services 2.1. 不同登录方式的写法 3. sysdba角色登录认证 3.1. 无 ...

  7. Android : 高通平台的HVX简介及调试

    一.HVX简介 HVX(“Hexagon矢量扩展”,Hexagon-六边形.Vector-矢量.Extensions-扩展)是Hexagon 680 DSP的典型特性,能够在执行图像处理应用中的计算负 ...

  8. kotlin之包

    在kotlin中包的概念在表达方式上与Java完全一样,不过kotlin中的包和目录没有关系,kotlin包仅仅是为了引用文件中的资源而设计的. package loaderman.bar fun p ...

  9. 11. Ingress及Ingress Controller(主nginx ingress controller)

    11. Ingress,Ingress Controller拥有七层代理调度能力 什么是Ingress: Ingress是授权入站连接到达集群服务的规则集合 Ingress是一个Kubernetes资 ...

  10. jQuery显示隐藏div的几种方法

    1.$("#demo").attr("style","display:none;");//隐藏div $("#demo" ...